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.

798 lines
22 KiB

  1. //===== Copyright (c) Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: PS3-specific font code that for historical reasons is hidden
  4. // in the materialsystem.
  5. //
  6. //==================================================================//
  7. #include "pch_materialsystem.h"
  8. #ifndef _PS3
  9. #define MATSYS_INTERNAL
  10. #endif
  11. #include "cmaterialsystem.h"
  12. #include "colorspace.h"
  13. #include "materialsystem/materialsystem_config.h"
  14. #include "materialsystem/imaterialproxyfactory.h"
  15. #include "IHardwareConfigInternal.h"
  16. #include "shadersystem.h"
  17. #include "texturemanager.h"
  18. #include "shaderlib/ShaderDLL.h"
  19. #include "tier1/callqueue.h"
  20. #include "vstdlib/jobthread.h"
  21. #include "cmatnullrendercontext.h"
  22. #include "datacache/iresourceaccesscontrol.h"
  23. #include "filesystem/IQueuedLoader.h"
  24. #include "filesystem/IXboxInstaller.h"
  25. #include "cdll_int.h"
  26. #include <cell/sysmodule.h>
  27. #include <cell/font.h>
  28. #include <cell/fontft.h>
  29. #include "../common/vgui_surfacelib/vguifont.h"
  30. #ifdef _PS3
  31. #include "ps3_pathinfo.h"
  32. #endif
  33. // NOTE: This must be the last file included!!!
  34. #include "tier0/memdbgon.h"
  35. static const CellFontLibrary *Fontlib();
  36. // in case I make HPS3FONT something other than just a pointer
  37. static inline CellFont *CellFontFromHandle( HPS3FONT &h )
  38. {
  39. return (CellFont *)h;
  40. }
  41. wchar_t g_wchFallbackGlyph = L'_';
  42. static inline bool ShouldFallBackToSystemFontForWChar( wchar_t wch, int &nFontTallAdjustment )
  43. {
  44. if ( ( wch == 0x00AE /*(R)*/ ) || ( wch == 0x2122 /*(TM)*/ ) )
  45. {
  46. nFontTallAdjustment = 1;
  47. return true;
  48. }
  49. return false;
  50. }
  51. #define TEXTURE_PAGE_HEIGHT 128 // copied from FontTextureCache.cpp, which for some reason hardcodes this. because there's multiple implementations
  52. // of the font cache strewn throughout various libraries all linked into the vgui dll, I didn't feel safe changing
  53. // it to just use larger textures.
  54. class CFallbackFont: public CellFont
  55. {
  56. protected:
  57. int m_nInitError;
  58. int m_nTall;
  59. CellFontHorizontalLayout m_hlayout;
  60. public:
  61. CFallbackFont(): m_nInitError(-1), m_nTall( -1 )
  62. {
  63. }
  64. void Init()
  65. {
  66. if( m_nInitError == CELL_OK )
  67. {
  68. // already initialized
  69. return ;
  70. }
  71. CellFontType fontType;
  72. fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
  73. fontType.map = CELL_FONT_MAP_UNICODE;
  74. m_nInitError = cellFontOpenFontset( Fontlib(), &fontType, this );
  75. if( m_nInitError == CELL_OK )
  76. {
  77. Warning("Cannot open fallback font, error 0x%X\n", m_nInitError );
  78. }
  79. }
  80. CellFontHorizontalLayout *GetHorizontalLayout()
  81. {
  82. return &m_hlayout;
  83. }
  84. int SetTall( int nTall )
  85. {
  86. if( m_nInitError != CELL_OK )
  87. {
  88. return m_nInitError;
  89. }
  90. if( nTall == m_nTall )
  91. {
  92. return CELL_OK;
  93. }
  94. float pointSize = nTall * 0.79f;
  95. cellFontSetScalePixel( this, pointSize, pointSize );
  96. // sometimes we ask for bigger fonts than the packer can handle. Also, because of accents etc, the font may poke out of the requested tall value.
  97. // The packer is for some reason hardcoded to a maximum height of 128.
  98. cellFontGetHorizontalLayout( this, &m_hlayout );
  99. if ( m_hlayout.lineHeight + m_hlayout.effectHeight > TEXTURE_PAGE_HEIGHT )
  100. {
  101. Warning("FAILSAFE: Fallback Font at '%d' tall is actually %d pixels high, but max texture page is %d. Shrinking to ",
  102. nTall, (int)(m_hlayout.lineHeight + m_hlayout.effectHeight), TEXTURE_PAGE_HEIGHT );
  103. do
  104. {
  105. pointSize *= 0.9;
  106. cellFontSetScalePixel( this, nTall, nTall );
  107. cellFontGetHorizontalLayout( this, &m_hlayout );
  108. }
  109. while ( ( m_hlayout.lineHeight + m_hlayout.effectHeight > TEXTURE_PAGE_HEIGHT ) && ( pointSize >= 1 ) );
  110. Warning( "%.2f\n", pointSize );
  111. }
  112. m_nTall = nTall;
  113. return CELL_OK;
  114. }
  115. void Shutdown()
  116. {
  117. if( m_nInitError == CELL_OK )
  118. {
  119. int nError = cellFontCloseFont( this );
  120. if( nError != CELL_OK )
  121. {
  122. Warning("Cannot close fallback font, error 0x%X\n", nError );
  123. }
  124. }
  125. }
  126. };
  127. CFallbackFont g_fallbackFont;
  128. void CMaterialSystem::InitializePS3Fonts()
  129. {
  130. m_vExtantFonts.EnsureCapacity(8);
  131. }
  132. class CTempFontHandle
  133. {
  134. public:
  135. CMaterialSystem * m_pMaterialSystem;
  136. MaterialLock_t m_hLock;
  137. CellFont * m_pNewFont;
  138. public:
  139. CTempFontHandle( CMaterialSystem * pMaterialSystem):
  140. m_pMaterialSystem( pMaterialSystem )
  141. {
  142. m_hLock = pMaterialSystem->Lock();
  143. m_pNewFont = new CellFont;
  144. }
  145. CellFont* DetachFont()
  146. {
  147. CellFont * pFont = m_pNewFont;
  148. m_pNewFont = NULL;
  149. return pFont;
  150. }
  151. ~CTempFontHandle()
  152. {
  153. if( m_pNewFont )
  154. {
  155. delete m_pNewFont;
  156. }
  157. m_pMaterialSystem->Unlock( m_hLock );
  158. }
  159. };
  160. HPS3FONT CMaterialSystem::OpenTrueTypeFont( const char *pFontname, int tall, int style )
  161. {
  162. CTempFontHandle hTemp( this );
  163. static int sUniquePositiveNumber = 0;
  164. // need absolute disk path, look in resource then platform
  165. char fontpath[MAX_PATH] = {0};
  166. struct fontTable_t
  167. {
  168. const char *pFontName;
  169. const char *pPath;
  170. bool m_bRestrictiveLoadIntoMemory;
  171. bool m_bAlwaysLoadIntoMemory;
  172. };
  173. int nCellError;
  174. if( !V_stricmp( pFontname, "system" ) )
  175. {
  176. CellFontType fontType;
  177. fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
  178. fontType.map = CELL_FONT_MAP_UNICODE;
  179. nCellError = cellFontOpenFontset( Fontlib(), &fontType, hTemp.m_pNewFont );
  180. }
  181. else if( !V_stricmp( pFontname, "japanese cjk latin" ) )
  182. {
  183. CellFontType fontType;
  184. fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
  185. fontType.map = CELL_FONT_MAP_UNICODE;
  186. nCellError = cellFontOpenFontset( Fontlib(), &fontType, hTemp.m_pNewFont );
  187. }
  188. else
  189. {
  190. // explicit mapping required, dvd searching too expensive
  191. static fontTable_t fontToFilename[] =
  192. {
  193. #include "shaderapidx9/fontremaptable.h"
  194. };
  195. // remap typeface to diskname
  196. char const *pDiskname = NULL;
  197. for ( int i=0; i<ARRAYSIZE( fontToFilename ); i++ )
  198. {
  199. if ( !V_stricmp( pFontname, fontToFilename[i].pFontName ) )
  200. {
  201. pDiskname = fontToFilename[i].pPath;
  202. break;
  203. }
  204. }
  205. if ( !pDiskname )
  206. {
  207. // not found
  208. DevWarning( "PS3: True Type Font: '%s' unknown.\n", pFontname );
  209. }
  210. else
  211. {
  212. Q_snprintf( fontpath, ARRAYSIZE( fontpath ), "%s/%s", g_pPS3PathInfo->GameImagePath(), pDiskname );
  213. }
  214. // if we failed to find the font, substitute a system font
  215. if ( fontpath[0] == 0 )
  216. {
  217. CellFontType fontType;
  218. fontType.type = CELL_FONT_TYPE_GOTHIC_JAPANESE_CJK_LATIN_SET;
  219. fontType.map = CELL_FONT_MAP_UNICODE;
  220. nCellError = cellFontOpenFontset( Fontlib(), &fontType, hTemp.m_pNewFont );
  221. }
  222. else
  223. {
  224. nCellError = cellFontOpenFontFile(
  225. Fontlib(),
  226. reinterpret_cast<uint8_t *>(fontpath),
  227. 0,
  228. ++sUniquePositiveNumber,
  229. hTemp.m_pNewFont );
  230. }
  231. }
  232. CellFont *pNewFont = NULL;
  233. if ( nCellError != CELL_FONT_OK )
  234. {
  235. Warning( "could not open font '%s': %x\n", pFontname, nCellError );
  236. return false;
  237. }
  238. else
  239. {
  240. pNewFont = hTemp.DetachFont(); // do not release the font structure
  241. m_vExtantFonts.AddToTail( pNewFont );
  242. }
  243. float pointSize = tall * 0.79f;
  244. cellFontSetScalePixel( pNewFont, pointSize, pointSize );
  245. // sometimes we ask for bigger fonts than the packer can handle. Also, because of accents etc, the font may poke out of the requested tall value.
  246. // The packer is for some reason hardcoded to a maximum height of 128.
  247. CellFontHorizontalLayout hlayout;
  248. cellFontGetHorizontalLayout( pNewFont, &hlayout );
  249. if ( hlayout.lineHeight + hlayout.effectHeight > TEXTURE_PAGE_HEIGHT )
  250. {
  251. Warning("FAILSAFE: %s at '%d' tall is actually %d pixels high, but max texture page is %d. Shrinking to ",
  252. pFontname, tall, (int)(hlayout.lineHeight + hlayout.effectHeight), TEXTURE_PAGE_HEIGHT );
  253. do
  254. {
  255. pointSize *= 0.9;
  256. cellFontSetScalePixel( pNewFont, tall, tall );
  257. cellFontGetHorizontalLayout( pNewFont, &hlayout );
  258. }
  259. while ( ( hlayout.lineHeight + hlayout.effectHeight > TEXTURE_PAGE_HEIGHT ) && (pointSize >= 1) );
  260. Warning( "%.2f\n", pointSize );
  261. }
  262. /*
  263. nCellError = cellFontGetHorizontalLayout( &m_sFont, &m_HorizontalLayout );
  264. AssertMsg2( nCellError == CELL_OK, "Could not get horizontal layout for font %s (%x)\n", m_szName.String(), nCellError );
  265. */
  266. /*
  267. nCellError = cellFontGetVerticalLayout( &m_sFont, &m_VerticalLayout );
  268. AssertMsg2( nCellError == CELL_OK, "Could not get vertical layout for font %s (%x)\n", m_szName.String(), nCellError );
  269. */
  270. return pNewFont;
  271. }
  272. void CMaterialSystem::CloseTrueTypeFont( HPS3FONT hFont )
  273. {
  274. MaterialLock_t hLock = Lock();
  275. // find the font in the vector
  276. CellFont *pFont = CellFontFromHandle( hFont );
  277. cellFontCloseFont( pFont );
  278. if ( m_vExtantFonts.FindAndFastRemove( pFont ) )
  279. {
  280. delete pFont;
  281. }
  282. else
  283. {
  284. AssertMsg1( false, "Tried to remove a font %x which wasn't in the material system's library\n", hFont );
  285. }
  286. Unlock( hLock );
  287. }
  288. bool CMaterialSystem::GetTrueTypeFontMetrics( HPS3FONT hFont, int nFallbackTall, wchar_t wchFirst, wchar_t wchLast, CPS3FontMetrics * RESTRICT pFontMetrics, CPS3CharMetrics * RESTRICT pCharMetrics )
  289. {
  290. MaterialLock_t hLock = Lock();
  291. int numChars = wchLast - wchFirst + 1;
  292. V_memset( pCharMetrics, 0, numChars * sizeof( CPS3CharMetrics ) );
  293. CellFont * RESTRICT pFont = CellFontFromHandle( hFont );
  294. int nCellError = cellFontGetHorizontalLayout( pFont, pFontMetrics );
  295. AssertMsg1( nCellError == CELL_OK, "Could not get horizontal layout for font (%x)\n", nCellError );
  296. // we will still need to go and fill in the max width once we've got the data for all the characters
  297. float fMaxWidth = 0;
  298. for ( int i = 0; i < numChars; i++ )
  299. {
  300. int nMetricsError = CELL_FONT_ERROR_FATAL;
  301. int nFallbackFontTallAdjustment = 0;
  302. if ( !ShouldFallBackToSystemFontForWChar( wchFirst + i, nFallbackFontTallAdjustment ) )
  303. {
  304. nMetricsError = cellFontGetCharGlyphMetrics( pFont, wchFirst + i, pCharMetrics + i );
  305. }
  306. if( nMetricsError != CELL_OK )
  307. {
  308. // try the fallback font
  309. int nFallbackError = g_fallbackFont.SetTall( nFallbackTall + nFallbackFontTallAdjustment );
  310. if( nFallbackError == CELL_OK )
  311. {
  312. nMetricsError = cellFontGetCharGlyphMetrics( &g_fallbackFont, wchFirst + i, pCharMetrics + i );
  313. }
  314. }
  315. if( nMetricsError != CELL_OK )
  316. {
  317. nMetricsError = cellFontGetCharGlyphMetrics( pFont, g_wchFallbackGlyph, pCharMetrics + i );
  318. }
  319. if ( nMetricsError == CELL_OK )
  320. {
  321. fMaxWidth = fmax( fMaxWidth, pCharMetrics[i].Horizontal.advance + 1 );
  322. }
  323. else
  324. {
  325. memset( pCharMetrics+i, 0, sizeof(*pCharMetrics) );
  326. }
  327. }
  328. pFontMetrics->fMaxWidth = fMaxWidth;
  329. Unlock( hLock );
  330. return nCellError == CELL_OK;
  331. }
  332. // encapsulates the ps3 fontlib renderer class with a RAII interface
  333. // so it binds/unbinds automatically
  334. class CFontRendererRAII
  335. {
  336. public:
  337. CFontRendererRAII( CellFont *pBoundFont );
  338. ~CFontRendererRAII();
  339. bool IsValid() { return m_nInitSuccess == CELL_FONT_OK; }
  340. protected:
  341. CellFontRenderer m_Renderer;
  342. CellFont *m_pFont;
  343. int m_nInitSuccess;
  344. };
  345. CFontRendererRAII::CFontRendererRAII( CellFont *pBoundFont ) : m_pFont(NULL)
  346. {
  347. CellFontRendererConfig config;
  348. CellFontRendererConfig_initialize( &config );
  349. // proper setup here
  350. m_nInitSuccess = cellFontCreateRenderer( Fontlib(), &config, &m_Renderer );
  351. if ( m_nInitSuccess != CELL_FONT_OK )
  352. {
  353. return ; // we have failed. we are failures. the stench of failure hangs upon us.
  354. }
  355. // connect the renderer to the font
  356. m_nInitSuccess = cellFontBindRenderer( pBoundFont, &m_Renderer );
  357. if ( m_nInitSuccess != CELL_FONT_OK )
  358. {
  359. return ; // we have failed. we are failures. the stench of failure hangs upon us.
  360. }
  361. m_pFont = pBoundFont;
  362. }
  363. CFontRendererRAII::~CFontRendererRAII()
  364. {
  365. if ( m_pFont )
  366. {
  367. cellFontUnbindRenderer( m_pFont );
  368. }
  369. cellFontDestroyRenderer( &m_Renderer );
  370. }
  371. // OPTIMIZATION OPPORTUNITY:
  372. // This can be made to run on the RSX instead of the PPU, if necessary.
  373. bool CMaterialSystem::GetTrueTypeGlyphs( HPS3FONT hFont, int nFallbackTall, int numChars, wchar_t *pWch, int *pOffsetX, int *pOffsetY, int * RESTRICT pWidth, int * RESTRICT pHeight, unsigned char *pRGBA, int *pRGBAOffset )
  374. {
  375. VPROF( "CMaterialSystem::GetTrueTypeGlyphs" );
  376. MaterialLock_t hLock = Lock();
  377. // Figure out the size of surface/texture we need to allocate
  378. int rtWidth = 0;
  379. int rtHeight = 0;
  380. for ( int i = 0; i < numChars; i++ )
  381. {
  382. //rtWidth += pWidth[i];
  383. rtWidth = MAX( rtWidth, pWidth[i] );
  384. rtHeight = MAX( rtHeight, pHeight[i] );
  385. }
  386. /*
  387. // per resolve() restrictions
  388. rtWidth = AlignValue( rtWidth, 32 );
  389. rtHeight = AlignValue( rtHeight, 32 );
  390. */
  391. if ( rtWidth == 0 || rtHeight == 0 )
  392. {
  393. AssertMsg2( false, "Tried to draw a %dx%d glyph! What are you trying to pull?!\n", rtWidth, rtHeight );
  394. Unlock( hLock );
  395. return false;
  396. }
  397. CellFont *pFont = CellFontFromHandle( hFont );
  398. CFontRendererRAII renderer( pFont ), *pFallbackRenderer = NULL;
  399. CellFontRenderSurface surface;
  400. CellFontGlyphMetrics metrics;
  401. CellFontImageTransInfo transInfo;
  402. CellFontHorizontalLayout hlayoutSlowWeShouldMoveThisIntoTheFontClass;
  403. cellFontRenderSurfaceInit( &surface, NULL, rtWidth, 1, rtWidth, rtHeight ); // the surface doesn't actually use the memory pointer (go figure)
  404. cellFontRenderSurfaceSetScissor( &surface, 0, 0, rtWidth, rtHeight );
  405. cellFontGetHorizontalLayout( pFont, &hlayoutSlowWeShouldMoveThisIntoTheFontClass );
  406. const int baselineY = floor(hlayoutSlowWeShouldMoveThisIntoTheFontClass.baseLineY);
  407. // struct XUIRect { int x, int y, int w, int h };
  408. // Draw the characters, stepping across the texture
  409. // int xCursor = 0;
  410. unsigned int successfulWrites = 0;
  411. for ( int i = 0; i < numChars; i++)
  412. {
  413. /*
  414. // FIXME: the drawRect params don't make much sense (should use "(xCursor+pWidth[i]), pHeight[i]", but then some characters disappear!)
  415. XUIRect drawRect = XUIRect( xCursor + pOffsetX[i], pOffsetY[i], rtWidth, rtHeight );
  416. cellFontRenderSurfaceSetScissor( &surface, drawRect.x, drawRect.y, drawRect.w, drawRect.h );
  417. wchar_t text[2] = { pWch[i], 0 };
  418. XuiDrawText( m_hDC, text, XUI_FONT_STYLE_NORMAL|XUI_FONT_STYLE_SINGLE_LINE|XUI_FONT_STYLE_NO_WORDWRAP, 0, &drawRect );
  419. xCursor += pWidth[i];
  420. */
  421. // draw one glyph to the surface
  422. int ps3suc = CELL_FONT_ERROR_FATAL;
  423. int nFallbackFontTallAdjustment = 0;
  424. if ( !ShouldFallBackToSystemFontForWChar( pWch[i], nFallbackFontTallAdjustment ) )
  425. {
  426. ps3suc = cellFontRenderCharGlyphImage( pFont, pWch[i], &surface, 0, 0, &metrics, &transInfo );
  427. }
  428. if ( ps3suc != CELL_OK )
  429. {
  430. if( CELL_OK == g_fallbackFont.SetTall( nFallbackTall + nFallbackFontTallAdjustment ) )
  431. {
  432. if( !pFallbackRenderer )
  433. pFallbackRenderer = new CFontRendererRAII( &g_fallbackFont );
  434. ps3suc = cellFontRenderCharGlyphImage( &g_fallbackFont, pWch[i], &surface, 0, 0, &metrics, &transInfo );
  435. }
  436. }
  437. if( ps3suc != CELL_OK )
  438. {
  439. ps3suc = cellFontRenderCharGlyphImage( pFont, g_wchFallbackGlyph, &surface, 0, 0, &metrics, &transInfo );
  440. }
  441. if ( ps3suc == CELL_OK )
  442. {
  443. // blit the glyph to the bitmap
  444. const int ibw = transInfo.imageWidthByte;
  445. const int iBearingY = ceilf(metrics.Horizontal.bearingY); // start the conversion early to avoid a LHS
  446. int destPitch = pWidth[i]*4; // distance between one row and the next IN BYTES
  447. unsigned char *pLinear = pRGBA + pRGBAOffset[i];
  448. // Clear out all pixels to black, since the source glyph size may not match the destination buffer size perfectly
  449. memset( pLinear, 0, pHeight[i] * destPitch );
  450. if ( transInfo.imageHeight==0 || transInfo.imageWidth==0 )
  451. {
  452. // this can happen for space or control characters
  453. // just blank out the destination box
  454. continue; // bail out and go to next character !
  455. }
  456. // work out the size of the region to copy -- which is the smaller of the source or destination buffer.
  457. // in theory these two should be identical, but the PS3 OS tends to overallocate space slightly
  458. // in its render surface, and sometimes the VGUI font code is expecting a blank column of pixels
  459. // where the PS3 generates none.
  460. // also we'll try to align the font glyph to the bottom of the destination rect, rather than
  461. // the top.
  462. int numLeftPadPixels = ( int )floorf( metrics.Horizontal.bearingX );
  463. numLeftPadPixels = MAX( 0, numLeftPadPixels );
  464. int iteratorMaxColumn = MIN( pWidth[i] - numLeftPadPixels, transInfo.imageWidth );
  465. int iteratorMaxRow = MIN( pHeight[i], transInfo.imageHeight );
  466. unsigned char *pLinearAligned = pLinear; // work out where to start writing into the image so that chars are aligned to bottom of rect
  467. pLinearAligned = pLinear + MAX(0, baselineY-iBearingY)*destPitch;
  468. // for ( int row = 0 ; row < transInfo.imageHeight ; ++row )
  469. for ( int row = 0 ; row < iteratorMaxRow; ++row )
  470. {
  471. uint32 * pRowStart = reinterpret_cast<uint32 *>(pLinearAligned + (row*destPitch)); // we will write the RGBA one word at a time
  472. for ( int col = 0 ; col < iteratorMaxColumn; ++col )
  473. {
  474. // white characters; only the alpha mask is copied from the rendered glyph
  475. // exception: totally absent regions are marked as just black
  476. uint8 a = transInfo.Image[ row * ibw + col ];
  477. *(pRowStart + col + numLeftPadPixels) = a ? 0xFFFFFF00 | a : 0 ;
  478. }
  479. }
  480. #if 0
  481. if ( FILE *f = fopen( "/app_home/dbgfonts.txt", "a+" ) )
  482. {
  483. fprintf( f, "% 4d %C [%dx%d]\n",
  484. pWch[i], pWch[i],
  485. transInfo.imageWidth, transInfo.imageHeight
  486. );
  487. fprintf( f, " [%d]\n",
  488. pWidth[i]
  489. );
  490. fprintf( f, " %0.5f %0.5f %0.5f\n",
  491. metrics.Horizontal.bearingX, metrics.width, metrics.Horizontal.advance
  492. );
  493. for ( int row = 0; row < MAX( MAX( pHeight[i], ceilf( metrics.height ) ), transInfo.imageHeight ); ++ row )
  494. {
  495. for ( int col = 0; col < MAX( pWidth[i], ceilf( metrics.Horizontal.advance ) ); ++ col )
  496. {
  497. uint8 a = transInfo.Image[ row * ibw + col ];
  498. fprintf( f, a ? ( (a>0x20) ? "X" : "*" ) : " " );
  499. }
  500. fprintf( f, "|\n" );
  501. }
  502. fprintf( f, "-----------------------------\n" );
  503. fclose(f);
  504. }
  505. #endif
  506. #if 0 // draw a line around the outer border for debugging
  507. for ( int row = 0 ; row < pHeight[i]; ++row )
  508. {
  509. *(reinterpret_cast<uint32 *>(pLinear + (row*destPitch))+0) = 0xFFFFFFFF;
  510. *(reinterpret_cast<uint32 *>(pLinear + (row*destPitch))+pWidth[i]-1) = 0xFFFFFFFF;
  511. }
  512. // top and bottom row
  513. memset( pLinear, 0xFF, pWidth[i] * 4 );
  514. memset( (pLinear + ((pHeight[i]-1)*destPitch)), 0xFF, pWidth[i] * 4 );
  515. #endif
  516. successfulWrites++;
  517. }
  518. else
  519. {
  520. AssertMsg2( false, "Couldn't draw u'%x', err %x\n", (unsigned int) *(pWch+i), ps3suc );
  521. }
  522. }
  523. if( pFallbackRenderer )
  524. delete pFallbackRenderer;
  525. Unlock( hLock );
  526. return successfulWrites > 0;
  527. }
  528. static int load_libfont_module()
  529. {
  530. int ret;
  531. ret = cellSysmoduleLoadModule( CELL_SYSMODULE_FONT );
  532. if ( ret == CELL_OK ) {
  533. ret = cellSysmoduleLoadModule( CELL_SYSMODULE_FREETYPE_TT );
  534. if ( ret == CELL_OK ) {
  535. ret = cellSysmoduleLoadModule( CELL_SYSMODULE_FONTFT );
  536. if ( ret == CELL_OK ) {
  537. return CELL_OK; // Success
  538. }
  539. // Error handling as follows (Unload all loads)
  540. cellSysmoduleUnloadModule( CELL_SYSMODULE_FREETYPE_TT );
  541. }
  542. cellSysmoduleUnloadModule( CELL_SYSMODULE_FONT );
  543. }
  544. return ret; // Error end
  545. }
  546. static void* fonts_malloc( void*obj, uint32_t size )
  547. {
  548. (void)obj;
  549. return malloc( size );
  550. }
  551. static void fonts_free( void*obj, void*p )
  552. {
  553. (void)obj;
  554. free( p );
  555. }
  556. static void* fonts_realloc( void*obj, void* p, uint32_t size )
  557. {
  558. (void)obj;
  559. return realloc( p, size );
  560. }
  561. static void* fonts_calloc( void*obj, uint32_t numb, uint32_t blockSize )
  562. {
  563. (void)obj;
  564. return calloc( numb, blockSize );
  565. }
  566. static int s_FontLibraryRefCount = 0;
  567. static uint32 *s_FontFileCache = NULL;
  568. static const CellFontLibrary *s_FontLibrary = NULL;
  569. static CellFontEntry *s_UserFontEntries = NULL;
  570. bool CMaterialSystem::PS3InitFontLibrary( unsigned fontFileCacheSizeInBytes, unsigned maxNumFonts )
  571. {
  572. if ( s_FontLibraryRefCount > 0 )
  573. {
  574. // don't need to load the font library, just add one to refcount
  575. ++s_FontLibraryRefCount;
  576. return true;
  577. }
  578. else if ( s_FontLibraryRefCount < 0 )
  579. {
  580. Error( "Font library refcount is %d!\n", s_FontLibraryRefCount );
  581. }
  582. else
  583. {
  584. ++s_FontLibraryRefCount;
  585. }
  586. VPROF("CMaterialSystem::PS3InitFontLibrary");
  587. if ( s_FontFileCache )
  588. {
  589. Warning("Tried to init font library twice without intervening unload\n");
  590. return false;
  591. }
  592. int ret;
  593. if ( (ret=load_libfont_module()) != CELL_OK )
  594. {
  595. Warning("Could not load font library: %x\n", ret);
  596. }
  597. maxNumFonts = maxNumFonts ? maxNumFonts : 1;
  598. if (s_FontFileCache)
  599. {
  600. Assert(false); // wasn't cleaned up?!
  601. delete[] s_FontFileCache;
  602. }
  603. if (s_UserFontEntries)
  604. {
  605. Assert(false); // wasn't cleaned up?!
  606. delete[] s_UserFontEntries;
  607. }
  608. s_FontFileCache = new uint32[fontFileCacheSizeInBytes >> 2];
  609. s_UserFontEntries = new CellFontEntry[maxNumFonts];
  610. CellFontConfig config;
  611. config.FileCache.buffer = s_FontFileCache;
  612. config.FileCache.size = fontFileCacheSizeInBytes;
  613. config.userFontEntrys = s_UserFontEntries;
  614. config.userFontEntryMax = maxNumFonts;
  615. ret = cellFontInit(&config);
  616. if ( ret == CELL_OK )
  617. {
  618. // can override malloc/free here:
  619. CellFontLibraryConfigFT ftConfig;
  620. CellFontLibraryConfigFT_initialize( &ftConfig );
  621. ftConfig.MemoryIF.Object = NULL;
  622. ftConfig.MemoryIF.Malloc = fonts_malloc;
  623. ftConfig.MemoryIF.Free = fonts_free;
  624. ftConfig.MemoryIF.Realloc = fonts_realloc;
  625. ftConfig.MemoryIF.Calloc = fonts_calloc;
  626. ret = cellFontInitLibraryFreeType( &ftConfig, &s_FontLibrary );
  627. if ( ret == CELL_OK )
  628. {
  629. g_fallbackFont.Init( );
  630. return true;
  631. }
  632. else
  633. {
  634. Warning( "cellFontInitLibraryFreeType failed, %x\n", ret );
  635. return false;
  636. }
  637. }
  638. else
  639. {
  640. Warning( "CellFontInit failed, %x\n", ret );
  641. return false;
  642. }
  643. }
  644. void *CMaterialSystem::PS3GetFontLibPtr()
  645. {
  646. return (void*)s_FontLibrary;
  647. }
  648. void CMaterialSystem::PS3DumpFontLibrary()
  649. {
  650. if ( s_FontLibraryRefCount <= 0 )
  651. {
  652. Warning("Font library refcount is %d during unload!\n", s_FontLibraryRefCount);
  653. return;
  654. }
  655. else if ( s_FontLibrary == NULL )
  656. {
  657. Warning("\t!!!FAILSAFE!!!\nPS3 font library refcount %d but was somehow unloaded!\n", s_FontLibraryRefCount);
  658. s_FontLibraryRefCount = 0;
  659. }
  660. else if ( --s_FontLibraryRefCount > 0 )
  661. { // refcount is still greater than one, don't need to unload
  662. return;
  663. }
  664. // Warning( "Font library was dumped with %d fonts left open.\n", m_vExtantFonts.Count() );
  665. if ( s_FontLibrary )
  666. {
  667. g_fallbackFont.Shutdown();
  668. cellFontEndLibrary( s_FontLibrary );
  669. cellFontEnd();
  670. delete[] s_FontFileCache;
  671. s_FontFileCache = NULL;
  672. // handled by cellFontEndLibrary: // delete s_FontLibrary;
  673. s_FontLibrary = NULL;
  674. delete[] s_UserFontEntries;
  675. s_UserFontEntries = NULL;
  676. cellSysmoduleUnloadModule( CELL_SYSMODULE_FONTFT );
  677. cellSysmoduleUnloadModule( CELL_SYSMODULE_FREETYPE_TT );
  678. cellSysmoduleUnloadModule( CELL_SYSMODULE_FONT );
  679. }
  680. }
  681. static const CellFontLibrary *Fontlib()
  682. {
  683. return s_FontLibrary;
  684. }