Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

994 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include <stdio.h>
  10. #include "hlfaceposer.h"
  11. #include "CloseCaptionTool.h"
  12. #include "choreowidgetdrawhelper.h"
  13. #include <vgui/ILocalize.h>
  14. extern vgui::ILocalize *g_pLocalize;
  15. using namespace vgui;
  16. CloseCaptionTool *g_pCloseCaptionTool = 0;
  17. #define STREAM_FONT "Tahoma"
  18. #define STREAM_POINTSIZE 12
  19. #define STREAM_LINEHEIGHT ( STREAM_POINTSIZE + 2 )
  20. #define STREAM_WEIGHT FW_NORMAL
  21. #define CAPTION_LINGER_TIME 1.5f
  22. // FIXME: Yahn, what is this, it's coded up as a DELAY before when the closed caption is displayed. That seems odd.
  23. #define CAPTION_PREDISPLAY_TIME 0.0f // 0.5f
  24. // A work unit is a pre-processed chunk of CC text to display
  25. // Any state changes (font/color/etc) cause a new work unit to be precomputed
  26. // Moving onto a new line also causes a new Work Unit
  27. // The width and height are stored so that layout can be quickly recomputed each frame
  28. class CCloseCaptionWorkUnit
  29. {
  30. public:
  31. CCloseCaptionWorkUnit();
  32. ~CCloseCaptionWorkUnit();
  33. void SetWidth( int w );
  34. int GetWidth() const;
  35. void SetHeight( int h );
  36. int GetHeight() const;
  37. void SetPos( int x, int y );
  38. void GetPos( int& x, int &y ) const;
  39. void SetBold( bool bold );
  40. bool GetBold() const;
  41. void SetItalic( bool ital );
  42. bool GetItalic() const;
  43. void SetStream( const wchar_t *stream );
  44. const wchar_t *GetStream() const;
  45. void SetColor( COLORREF clr );
  46. COLORREF GetColor() const;
  47. int GetFontNumber() const
  48. {
  49. return CloseCaptionTool::GetFontNumber( m_bBold, m_bItalic );
  50. }
  51. void Dump()
  52. {
  53. char buf[ 2048 ];
  54. g_pLocalize->ConvertUnicodeToANSI( GetStream(), buf, sizeof( buf ) );
  55. Msg( "x = %i, y = %i, w = %i h = %i text %s\n", m_nX, m_nY, m_nWidth, m_nHeight, buf );
  56. }
  57. private:
  58. int m_nX;
  59. int m_nY;
  60. int m_nWidth;
  61. int m_nHeight;
  62. bool m_bBold;
  63. bool m_bItalic;
  64. wchar_t *m_pszStream;
  65. COLORREF m_Color;
  66. };
  67. CCloseCaptionWorkUnit::CCloseCaptionWorkUnit() :
  68. m_nWidth(0),
  69. m_nHeight(0),
  70. m_bBold(false),
  71. m_bItalic(false),
  72. m_pszStream(0),
  73. m_Color( RGB( 255, 255, 255 ) )
  74. {
  75. }
  76. CCloseCaptionWorkUnit::~CCloseCaptionWorkUnit()
  77. {
  78. delete[] m_pszStream;
  79. m_pszStream = NULL;
  80. }
  81. void CCloseCaptionWorkUnit::SetWidth( int w )
  82. {
  83. m_nWidth = w;
  84. }
  85. int CCloseCaptionWorkUnit::GetWidth() const
  86. {
  87. return m_nWidth;
  88. }
  89. void CCloseCaptionWorkUnit::SetHeight( int h )
  90. {
  91. m_nHeight = h;
  92. }
  93. int CCloseCaptionWorkUnit::GetHeight() const
  94. {
  95. return m_nHeight;
  96. }
  97. void CCloseCaptionWorkUnit::SetPos( int x, int y )
  98. {
  99. m_nX = x;
  100. m_nY = y;
  101. }
  102. void CCloseCaptionWorkUnit::GetPos( int& x, int &y ) const
  103. {
  104. x = m_nX;
  105. y = m_nY;
  106. }
  107. void CCloseCaptionWorkUnit::SetBold( bool bold )
  108. {
  109. m_bBold = bold;
  110. }
  111. bool CCloseCaptionWorkUnit::GetBold() const
  112. {
  113. return m_bBold;
  114. }
  115. void CCloseCaptionWorkUnit::SetItalic( bool ital )
  116. {
  117. m_bItalic = ital;
  118. }
  119. bool CCloseCaptionWorkUnit::GetItalic() const
  120. {
  121. return m_bItalic;
  122. }
  123. void CCloseCaptionWorkUnit::SetStream( const wchar_t *stream )
  124. {
  125. delete[] m_pszStream;
  126. m_pszStream = NULL;
  127. int len = wcslen( stream );
  128. Assert( len < 4096 );
  129. m_pszStream = new wchar_t[ len + 1 ];
  130. wcsncpy( m_pszStream, stream, len );
  131. m_pszStream[ len ] = L'\0';
  132. }
  133. const wchar_t *CCloseCaptionWorkUnit::GetStream() const
  134. {
  135. return m_pszStream ? m_pszStream : L"";
  136. }
  137. void CCloseCaptionWorkUnit::SetColor( COLORREF clr )
  138. {
  139. m_Color = clr;
  140. }
  141. COLORREF CCloseCaptionWorkUnit::GetColor() const
  142. {
  143. return m_Color;
  144. }
  145. //-----------------------------------------------------------------------------
  146. // Purpose:
  147. //-----------------------------------------------------------------------------
  148. class CCloseCaptionItem
  149. {
  150. public:
  151. CCloseCaptionItem(
  152. wchar_t *stream,
  153. float timetolive,
  154. float predisplay,
  155. bool valid
  156. ) :
  157. m_flTimeToLive( 0.0f ),
  158. m_bValid( false ),
  159. m_nTotalWidth( 0 ),
  160. m_nTotalHeight( 0 ),
  161. m_bSizeComputed( false )
  162. {
  163. SetStream( stream );
  164. SetTimeToLive( timetolive );
  165. SetPreDisplayTime( CAPTION_PREDISPLAY_TIME + predisplay );
  166. m_bValid = valid;
  167. m_bSizeComputed = false;
  168. }
  169. CCloseCaptionItem( const CCloseCaptionItem& src )
  170. {
  171. SetStream( src.m_szStream );
  172. m_flTimeToLive = src.m_flTimeToLive;
  173. m_bValid = src.m_bValid;
  174. }
  175. ~CCloseCaptionItem( void )
  176. {
  177. while ( m_Work.Count() > 0 )
  178. {
  179. CCloseCaptionWorkUnit *unit = m_Work[ 0 ];
  180. m_Work.Remove( 0 );
  181. delete unit;
  182. }
  183. }
  184. void SetStream( const wchar_t *stream)
  185. {
  186. wcsncpy( m_szStream, stream, sizeof( m_szStream ) / sizeof( wchar_t ) );
  187. }
  188. const wchar_t *GetStream() const
  189. {
  190. return m_szStream;
  191. }
  192. void SetTimeToLive( float ttl )
  193. {
  194. m_flTimeToLive = ttl;
  195. }
  196. float GetTimeToLive( void ) const
  197. {
  198. return m_flTimeToLive;
  199. }
  200. bool IsValid() const
  201. {
  202. return m_bValid;
  203. }
  204. void SetHeight( int h )
  205. {
  206. m_nTotalHeight = h;
  207. }
  208. int GetHeight() const
  209. {
  210. return m_nTotalHeight;
  211. }
  212. void SetWidth( int w )
  213. {
  214. m_nTotalWidth = w;
  215. }
  216. int GetWidth() const
  217. {
  218. return m_nTotalWidth;
  219. }
  220. void AddWork( CCloseCaptionWorkUnit *unit )
  221. {
  222. m_Work.AddToTail( unit );
  223. }
  224. int GetNumWorkUnits() const
  225. {
  226. return m_Work.Count();
  227. }
  228. CCloseCaptionWorkUnit *GetWorkUnit( int index )
  229. {
  230. Assert( index >= 0 && index < m_Work.Count() );
  231. return m_Work[ index ];
  232. }
  233. void SetSizeComputed( bool computed )
  234. {
  235. m_bSizeComputed = computed;
  236. }
  237. bool GetSizeComputed() const
  238. {
  239. return m_bSizeComputed;
  240. }
  241. void SetPreDisplayTime( float t )
  242. {
  243. m_flPreDisplayTime = t;
  244. }
  245. float GetPreDisplayTime() const
  246. {
  247. return m_flPreDisplayTime;
  248. }
  249. private:
  250. wchar_t m_szStream[ 256 ];
  251. float m_flPreDisplayTime;
  252. float m_flTimeToLive;
  253. bool m_bValid;
  254. int m_nTotalWidth;
  255. int m_nTotalHeight;
  256. bool m_bSizeComputed;
  257. CUtlVector< CCloseCaptionWorkUnit * > m_Work;
  258. };
  259. ICloseCaptionManager *closecaptionmanager = NULL;
  260. CloseCaptionTool::CloseCaptionTool( mxWindow *parent )
  261. : IFacePoserToolWindow( "CloseCaptionTool", "Close Caption" ), mxWindow( parent, 0, 0, 0, 0 )
  262. {
  263. m_nLastItemCount = -1;
  264. closecaptionmanager = this;
  265. m_hFonts[ CCFONT_NORMAL ] = CreateFont(
  266. -STREAM_POINTSIZE,
  267. 0,
  268. 0,
  269. 0,
  270. STREAM_WEIGHT,
  271. FALSE,
  272. FALSE,
  273. FALSE,
  274. DEFAULT_CHARSET,
  275. OUT_TT_PRECIS,
  276. CLIP_DEFAULT_PRECIS,
  277. ANTIALIASED_QUALITY,
  278. DEFAULT_PITCH,
  279. STREAM_FONT );
  280. m_hFonts[ CCFONT_ITALIC ] = CreateFont(
  281. -STREAM_POINTSIZE,
  282. 0,
  283. 0,
  284. 0,
  285. STREAM_WEIGHT,
  286. TRUE,
  287. FALSE,
  288. FALSE,
  289. DEFAULT_CHARSET,
  290. OUT_TT_PRECIS,
  291. CLIP_DEFAULT_PRECIS,
  292. ANTIALIASED_QUALITY,
  293. DEFAULT_PITCH,
  294. STREAM_FONT );
  295. m_hFonts[ CCFONT_BOLD ] = CreateFont(
  296. -STREAM_POINTSIZE,
  297. 0,
  298. 0,
  299. 0,
  300. 700,
  301. FALSE,
  302. FALSE,
  303. FALSE,
  304. DEFAULT_CHARSET,
  305. OUT_TT_PRECIS,
  306. CLIP_DEFAULT_PRECIS,
  307. ANTIALIASED_QUALITY,
  308. DEFAULT_PITCH,
  309. STREAM_FONT );
  310. m_hFonts[ CCFONT_ITALICBOLD ] = CreateFont(
  311. -STREAM_POINTSIZE,
  312. 0,
  313. 0,
  314. 0,
  315. 700,
  316. TRUE,
  317. FALSE,
  318. FALSE,
  319. DEFAULT_CHARSET,
  320. OUT_TT_PRECIS,
  321. CLIP_DEFAULT_PRECIS,
  322. ANTIALIASED_QUALITY,
  323. DEFAULT_PITCH,
  324. STREAM_FONT );
  325. }
  326. CloseCaptionTool::~CloseCaptionTool( void )
  327. {
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Purpose:
  331. // Input : dt -
  332. //-----------------------------------------------------------------------------
  333. void CloseCaptionTool::Think( float dt )
  334. {
  335. int c = m_Items.Count();
  336. int i;
  337. // Pass one decay all timers
  338. for ( i = 0 ; i < c ; ++i )
  339. {
  340. CCloseCaptionItem *item = m_Items[ i ];
  341. float predisplay = item->GetPreDisplayTime();
  342. if ( predisplay > 0.0f )
  343. {
  344. predisplay -= dt;
  345. predisplay = max( 0.0f, predisplay );
  346. item->SetPreDisplayTime( predisplay );
  347. }
  348. else
  349. {
  350. // remove time from actual playback
  351. float ttl = item->GetTimeToLive();
  352. ttl -= dt;
  353. ttl = max( 0.0f, ttl );
  354. item->SetTimeToLive( ttl );
  355. }
  356. }
  357. // Pass two, remove from head until we get to first item with time remaining
  358. bool foundfirstnondeletion = false;
  359. for ( i = 0 ; i < c ; ++i )
  360. {
  361. CCloseCaptionItem *item = m_Items[ i ];
  362. // Skip items not yet showing...
  363. float predisplay = item->GetPreDisplayTime();
  364. if ( predisplay > 0.0f )
  365. {
  366. continue;
  367. }
  368. float ttl = item->GetTimeToLive();
  369. if ( ttl > 0.0f )
  370. {
  371. foundfirstnondeletion = true;
  372. continue;
  373. }
  374. // Skip the remainder of the items after we find the first/oldest active item
  375. if ( foundfirstnondeletion )
  376. {
  377. continue;
  378. }
  379. delete item;
  380. m_Items.Remove( i );
  381. --i;
  382. --c;
  383. }
  384. if ( m_Items.Count() != m_nLastItemCount )
  385. {
  386. redraw();
  387. }
  388. m_nLastItemCount = m_Items.Count();
  389. }
  390. struct VisibleStreamItem
  391. {
  392. int height;
  393. CCloseCaptionItem *item;
  394. };
  395. void CloseCaptionTool::redraw()
  396. {
  397. if ( !ToolCanDraw() )
  398. return;
  399. CChoreoWidgetDrawHelper drawHelper( this );
  400. HandleToolRedraw( drawHelper );
  401. RECT rcOutput;
  402. drawHelper.GetClientRect( rcOutput );
  403. RECT rcText = rcOutput;
  404. drawHelper.DrawFilledRect( RGB( 0, 0, 0 ), rcText );
  405. drawHelper.DrawOutlinedRect( RGB( 200, 245, 150 ), PS_SOLID, 2, rcText );
  406. InflateRect( &rcText, -4, 0 );
  407. int avail_width = rcText.right - rcText.left;
  408. int totalheight = 0;
  409. int i;
  410. CUtlVector< VisibleStreamItem > visibleitems;
  411. int c = m_Items.Count();
  412. for ( i = 0; i < c; i++ )
  413. {
  414. CCloseCaptionItem *item = m_Items[ i ];
  415. // Not ready for display yet.
  416. if ( item->GetPreDisplayTime() > 0.0f )
  417. {
  418. continue;
  419. }
  420. if ( !item->GetSizeComputed() )
  421. {
  422. ComputeStreamWork( drawHelper, avail_width, item );
  423. }
  424. int itemheight = item->GetHeight();
  425. totalheight += itemheight;
  426. VisibleStreamItem si;
  427. si.height = itemheight;
  428. si.item = item;
  429. visibleitems.AddToTail( si );
  430. }
  431. rcText.bottom -= 2;
  432. rcText.top = rcText.bottom - totalheight;
  433. // Now draw them
  434. c = visibleitems.Count();
  435. for ( i = 0; i < c; i++ )
  436. {
  437. VisibleStreamItem *si = &visibleitems[ i ];
  438. int height = si->height;
  439. CCloseCaptionItem *item = si->item;
  440. rcText.bottom = rcText.top + height;
  441. DrawStream( drawHelper, rcText, item );
  442. OffsetRect( &rcText, 0, height );
  443. if ( rcText.top >= rcOutput.bottom )
  444. break;
  445. }
  446. }
  447. int CloseCaptionTool::handleEvent( mxEvent *event )
  448. {
  449. //MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  450. int iret = 0;
  451. if ( HandleToolEvent( event ) )
  452. {
  453. return iret;
  454. }
  455. return iret;
  456. }
  457. bool CloseCaptionTool::PaintBackground()
  458. {
  459. redraw();
  460. return false;
  461. }
  462. void CloseCaptionTool::Reset( void )
  463. {
  464. while ( m_Items.Count() > 0 )
  465. {
  466. CCloseCaptionItem *i = m_Items[ 0 ];
  467. delete i;
  468. m_Items.Remove( 0 );
  469. }
  470. }
  471. void CloseCaptionTool::Process( char const *tokenname, float duration, int languageid )
  472. {
  473. bool valid = true;
  474. wchar_t stream[ 256 ];
  475. if ( !LookupUnicodeText( languageid, tokenname, stream, sizeof( stream ) / sizeof( wchar_t ) ) )
  476. {
  477. valid = false;
  478. g_pLocalize->ConvertANSIToUnicode( va( "--> Missing Caption[%s]", tokenname ), stream, sizeof( stream ) );
  479. }
  480. if ( !wcsncmp( stream, L"!!!", wcslen( L"!!!" ) ) )
  481. {
  482. // It's in the text file, but hasn't been translated...
  483. valid = false;
  484. }
  485. // Nothing to do...
  486. if ( wcslen( stream ) == 0 )
  487. {
  488. return;
  489. }
  490. float delay = 0.0f;
  491. wchar_t phrase[ 1024 ];
  492. wchar_t *out = phrase;
  493. for ( const wchar_t *curpos = stream; curpos && *curpos != L'\0'; ++curpos )
  494. {
  495. wchar_t cmd[ 256 ];
  496. wchar_t args[ 256 ];
  497. if ( SplitCommand( &curpos, cmd, args ) )
  498. {
  499. if ( !wcscmp( cmd, L"delay" ) )
  500. {
  501. // End current phrase
  502. *out = L'\0';
  503. if ( wcslen( phrase ) > 0 )
  504. {
  505. CCloseCaptionItem *item = new CCloseCaptionItem( phrase, duration + CAPTION_LINGER_TIME, delay, valid );
  506. m_Items.AddToTail( item );
  507. }
  508. // Start new phrase
  509. out = phrase;
  510. // Delay must be positive
  511. delay = max( 0.0f, (float)wcstod( args, NULL ) );
  512. continue;
  513. }
  514. }
  515. *out++ = *curpos;
  516. }
  517. // End final phrase, if any
  518. *out = L'\0';
  519. if ( wcslen( phrase ) > 0 )
  520. {
  521. CCloseCaptionItem *item = new CCloseCaptionItem( phrase, duration + CAPTION_LINGER_TIME, delay, valid );
  522. m_Items.AddToTail( item );
  523. }
  524. }
  525. bool CloseCaptionTool::LookupUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count )
  526. {
  527. wchar_t *outstr = g_pLocalize->Find( token );
  528. if ( !outstr )
  529. {
  530. wcsncpy( outbuf, L"<can't find entry>", count );
  531. return false;
  532. }
  533. wcsncpy( outbuf, outstr, count );
  534. return true;
  535. }
  536. bool CloseCaptionTool::LookupStrippedUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count )
  537. {
  538. wchar_t *outstr = g_pLocalize->Find( token );
  539. if ( !outstr )
  540. {
  541. wcsncpy( outbuf, L"<can't find entry>", count );
  542. return false;
  543. }
  544. const wchar_t *curpos = outstr;
  545. wchar_t *out = outbuf;
  546. size_t outlen = 0;
  547. for ( ;
  548. curpos && *curpos != L'\0' && outlen < count;
  549. ++curpos )
  550. {
  551. wchar_t cmd[ 256 ];
  552. wchar_t args[ 256 ];
  553. if ( SplitCommand( &curpos, cmd, args ) )
  554. {
  555. continue;
  556. }
  557. *out++ = *curpos;
  558. ++outlen;
  559. }
  560. *out = L'\0';
  561. return true;
  562. }
  563. bool CloseCaptionTool::SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t *args ) const
  564. {
  565. const wchar_t *in = *ppIn;
  566. const wchar_t *oldin = in;
  567. if ( in[0] != L'<' )
  568. {
  569. *ppIn += ( oldin - in );
  570. return false;
  571. }
  572. args[ 0 ] = 0;
  573. cmd[ 0 ]= 0;
  574. wchar_t *out = cmd;
  575. in++;
  576. while ( *in != L'\0' && *in != L':' && *in != L'>' && !isspace( *in ) )
  577. {
  578. *out++ = *in++;
  579. }
  580. *out = L'\0';
  581. if ( *in != L':' )
  582. {
  583. *ppIn += ( in - oldin );
  584. return true;
  585. }
  586. in++;
  587. out = args;
  588. while ( *in != L'\0' && *in != L'>' )
  589. {
  590. *out++ = *in++;
  591. }
  592. *out = L'\0';
  593. //if ( *in == L'>' )
  594. // in++;
  595. *ppIn += ( in - oldin );
  596. return true;
  597. }
  598. struct WorkUnitParams
  599. {
  600. WorkUnitParams()
  601. {
  602. Q_memset( stream, 0, sizeof( stream ) );
  603. out = stream;
  604. x = 0;
  605. y = 0;
  606. width = 0;
  607. bold = italic = false;
  608. clr = RGB( 255, 255, 255 );
  609. newline = false;
  610. }
  611. ~WorkUnitParams()
  612. {
  613. }
  614. void Finalize()
  615. {
  616. *out = L'\0';
  617. }
  618. void Next()
  619. {
  620. // Restart output
  621. Q_memset( stream, 0, sizeof( stream ) );
  622. out = stream;
  623. x += width;
  624. width = 0;
  625. // Leave bold, italic and color alone!!!
  626. if ( newline )
  627. {
  628. newline = false;
  629. x = 0;
  630. y += STREAM_LINEHEIGHT;
  631. }
  632. }
  633. int GetFontNumber()
  634. {
  635. return CloseCaptionTool::GetFontNumber( bold, italic );
  636. }
  637. wchar_t stream[ 1024 ];
  638. wchar_t *out;
  639. int x;
  640. int y;
  641. int width;
  642. bool bold;
  643. bool italic;
  644. COLORREF clr;
  645. bool newline;
  646. };
  647. void CloseCaptionTool::AddWorkUnit( CCloseCaptionItem *item,
  648. WorkUnitParams& params )
  649. {
  650. params.Finalize();
  651. if ( wcslen( params.stream ) > 0 )
  652. {
  653. CCloseCaptionWorkUnit *wu = new CCloseCaptionWorkUnit();
  654. wu->SetStream( params.stream );
  655. wu->SetColor( params.clr );
  656. wu->SetBold( params.bold );
  657. wu->SetItalic( params.italic );
  658. wu->SetWidth( params.width );
  659. wu->SetHeight( STREAM_LINEHEIGHT );
  660. wu->SetPos( params.x, params.y );
  661. int curheight = item->GetHeight();
  662. int curwidth = item->GetWidth();
  663. curheight = max( curheight, params.y + wu->GetHeight() );
  664. curwidth = max( curwidth, params.x + params.width );
  665. item->SetHeight( curheight );
  666. item->SetWidth( curwidth );
  667. // Add it
  668. item->AddWork( wu );
  669. params.Next();
  670. }
  671. }
  672. void CloseCaptionTool::ComputeStreamWork( CChoreoWidgetDrawHelper &helper, int available_width, CCloseCaptionItem *item )
  673. {
  674. // Start with a clean param block
  675. WorkUnitParams params;
  676. const wchar_t *curpos = item->GetStream();
  677. CUtlVector< COLORREF > colorStack;
  678. for ( ; curpos && *curpos != L'\0'; ++curpos )
  679. {
  680. wchar_t cmd[ 256 ];
  681. wchar_t args[ 256 ];
  682. if ( SplitCommand( &curpos, cmd, args ) )
  683. {
  684. if ( !wcscmp( cmd, L"cr" ) )
  685. {
  686. params.newline = true;
  687. AddWorkUnit( item, params);
  688. }
  689. else if ( !wcscmp( cmd, L"clr" ) )
  690. {
  691. AddWorkUnit( item, params );
  692. if ( args[0] == 0 && colorStack.Count()>= 2)
  693. {
  694. colorStack.Remove( colorStack.Count() - 1 );
  695. params.clr = colorStack[ colorStack.Count() - 1 ];
  696. }
  697. else
  698. {
  699. int r = 0, g = 0, b = 0;
  700. COLORREF newcolor;
  701. if ( 3 == swscanf( args, L"%i,%i,%i", &r, &g, &b ) )
  702. {
  703. newcolor = RGB( r, g, b );
  704. colorStack.AddToTail( newcolor );
  705. params.clr = colorStack[ colorStack.Count() - 1 ];
  706. }
  707. }
  708. }
  709. else if ( !wcscmp( cmd, L"playerclr" ) )
  710. {
  711. AddWorkUnit( item, params );
  712. if ( args[0] == 0 && colorStack.Count()>= 2)
  713. {
  714. colorStack.Remove( colorStack.Count() - 1 );
  715. params.clr = colorStack[ colorStack.Count() - 1 ];
  716. }
  717. else
  718. {
  719. // player and npc color selector
  720. // e.g.,. 255,255,255:200,200,200
  721. int pr = 0, pg = 0, pb = 0, nr = 0, ng = 0, nb = 0;
  722. COLORREF newcolor;
  723. if ( 6 == swscanf( args, L"%i,%i,%i:%i,%i,%i", &pr, &pg, &pb, &nr, &ng, &nb ) )
  724. {
  725. // FIXME: nothing in .vcds is ever from the player...
  726. newcolor = /*item->IsFromPlayer()*/ false ? RGB( pr, pg, pb ) : RGB( nr, ng, nb );
  727. colorStack.AddToTail( newcolor );
  728. params.clr = colorStack[ colorStack.Count() - 1 ];
  729. }
  730. }
  731. }
  732. else if ( !wcscmp( cmd, L"I" ) )
  733. {
  734. AddWorkUnit( item, params );
  735. params.italic = !params.italic;
  736. }
  737. else if ( !wcscmp( cmd, L"B" ) )
  738. {
  739. AddWorkUnit( item, params );
  740. params.bold = !params.bold;
  741. }
  742. continue;
  743. }
  744. HFONT useF = m_hFonts[ params.GetFontNumber() ];
  745. int w = helper.CalcTextWidthW( useF, L"%c", *curpos );
  746. if ( ( params.x + params.width ) + w > available_width )
  747. {
  748. params.newline = true;
  749. AddWorkUnit( item, params );
  750. }
  751. *params.out++ = *curpos;
  752. params.width += w;
  753. }
  754. // Add the final unit.
  755. params.newline = true;
  756. AddWorkUnit( item, params );
  757. item->SetSizeComputed( true );
  758. // DumpWork( item );
  759. }
  760. void CloseCaptionTool:: DumpWork( CCloseCaptionItem *item )
  761. {
  762. int c = item->GetNumWorkUnits();
  763. for ( int i = 0 ; i < c; ++i )
  764. {
  765. CCloseCaptionWorkUnit *wu = item->GetWorkUnit( i );
  766. wu->Dump();
  767. }
  768. }
  769. void CloseCaptionTool::DrawStream( CChoreoWidgetDrawHelper &helper, RECT &rcText, CCloseCaptionItem *item )
  770. {
  771. int c = item->GetNumWorkUnits();
  772. RECT rcOut;
  773. rcOut.left = rcText.left;
  774. for ( int i = 0 ; i < c; ++i )
  775. {
  776. int x = 0;
  777. int y = 0;
  778. CCloseCaptionWorkUnit *wu = item->GetWorkUnit( i );
  779. HFONT useF = m_hFonts[ wu->GetFontNumber() ];
  780. wu->GetPos( x, y );
  781. rcOut.left = rcText.left + x;
  782. rcOut.right = rcOut.left + wu->GetWidth();
  783. rcOut.top = rcText.top + y;
  784. rcOut.bottom = rcOut.top + wu->GetHeight();
  785. COLORREF useColor = wu->GetColor();
  786. if ( !item->IsValid() )
  787. {
  788. useColor = RGB( 255, 255, 255 );
  789. rcOut.right += 2;
  790. helper.DrawFilledRect( RGB( 100, 100, 40 ), rcOut );
  791. }
  792. helper.DrawColoredTextW( useF, useColor,
  793. rcOut, L"%s", wu->GetStream() );
  794. }
  795. }
  796. int CloseCaptionTool::GetFontNumber( bool bold, bool italic )
  797. {
  798. if ( bold || italic )
  799. {
  800. if( bold && italic )
  801. {
  802. return CloseCaptionTool::CCFONT_ITALICBOLD;
  803. }
  804. if ( bold )
  805. {
  806. return CloseCaptionTool::CCFONT_BOLD;
  807. }
  808. if ( italic )
  809. {
  810. return CloseCaptionTool::CCFONT_ITALIC;
  811. }
  812. }
  813. return CloseCaptionTool::CCFONT_NORMAL;
  814. }