Counter Strike : Global Offensive Source Code
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.

992 lines
18 KiB

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