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.

396 lines
13 KiB

  1. //-----------------------------------------------------------------------------
  2. // Name: FontMakerWnd.cpp
  3. //
  4. // Desc: The window and scroll view class for the fontmaker app
  5. //
  6. // Hist: 09.06.02 - Revised Fontmaker sample
  7. //
  8. // Copyright (c) Microsoft Corporation. All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "FontMaker.h"
  12. #include "Glyphs.h"
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. extern CTextureFont g_Font;
  19. BOOL g_bIsGlyphSelected = FALSE;
  20. int g_iSelectedGlyphNum = 0;
  21. WCHAR g_cSelectedGlyph = '\0';
  22. GLYPH_ATTR* g_pSelectedGylph = NULL;
  23. // Colors
  24. #define COLOR_WHITE ( RGB(255,255,255) )
  25. #define COLOR_BLACK ( RGB( 0, 0, 0) )
  26. #define COLOR_BLUE ( RGB( 0, 0,255) )
  27. #define COLOR_RED ( RGB(255, 0, 0) )
  28. #define COLOR_DARKRED ( RGB(128, 0, 0) )
  29. //-----------------------------------------------------------------------------
  30. // CFontMakerFrameWnd
  31. //-----------------------------------------------------------------------------
  32. IMPLEMENT_DYNCREATE(CFontMakerFrameWnd, CFrameWnd)
  33. BEGIN_MESSAGE_MAP(CFontMakerFrameWnd, CFrameWnd)
  34. //{{AFX_MSG_MAP(CFontMakerFrameWnd)
  35. ON_WM_CREATE()
  36. //}}AFX_MSG_MAP
  37. END_MESSAGE_MAP()
  38. int CFontMakerFrameWnd::OnCreate( LPCREATESTRUCT pCreateStruct )
  39. {
  40. if( CFrameWnd::OnCreate( pCreateStruct ) == -1 )
  41. return -1;
  42. // Create a docked dialog bar
  43. EnableDocking( CBRS_ALIGN_ANY );
  44. if( !m_wndDialogBar.Create( this, IDD_DIALOGBAR,
  45. CBRS_LEFT, IDD_DIALOGBAR ) )
  46. {
  47. TRACE0("Failed to create DlgBar\n");
  48. return -1;
  49. }
  50. return 0;
  51. }
  52. //-----------------------------------------------------------------------------
  53. // CFontMakerView
  54. //-----------------------------------------------------------------------------
  55. IMPLEMENT_DYNCREATE(CFontMakerView, CScrollView)
  56. BEGIN_MESSAGE_MAP(CFontMakerView, CScrollView)
  57. //{{AFX_MSG_MAP(CFontMakerView)
  58. ON_WM_LBUTTONDOWN()
  59. ON_WM_ERASEBKGND()
  60. ON_WM_KEYDOWN()
  61. //}}AFX_MSG_MAP
  62. END_MESSAGE_MAP()
  63. //-----------------------------------------------------------------------------
  64. // Name: ~CFontMakerView()
  65. // Desc: Destructor with special cleanup
  66. //-----------------------------------------------------------------------------
  67. CFontMakerView::~CFontMakerView()
  68. {
  69. // Cleanup before exitting
  70. m_memDC.DeleteDC();
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Name: OnInitialUpdate()
  74. // Desc: Called when the view is created.
  75. //-----------------------------------------------------------------------------
  76. void CFontMakerView::OnInitialUpdate()
  77. {
  78. // Set the scroll bars
  79. CScrollView::OnInitialUpdate();
  80. CSize szTotal( g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight );
  81. SetScrollSizes( MM_TEXT, szTotal );
  82. CPoint ptCenter( 0, 0 );
  83. CenterOnPoint( ptCenter );
  84. // Create a secondary DC, used for drawing
  85. m_memDC.CreateCompatibleDC( GetDC() );
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Name: OnEraseBkgnd()
  89. // Desc: Overridden function to prevent the view from flickering during resizes
  90. // and redraws
  91. //-----------------------------------------------------------------------------
  92. BOOL CFontMakerView::OnEraseBkgnd( CDC* pDC )
  93. {
  94. return TRUE;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Name: RenderSelectedGlyph()
  98. // Desc: Highlight the selected glyph
  99. //-----------------------------------------------------------------------------
  100. VOID RenderSelectedGlyph( CDC* pDC )
  101. {
  102. // If no glyph is selected, return
  103. if( FALSE == g_bIsGlyphSelected )
  104. return;
  105. HRGN rgn = CreateRectRgn( 0, 0, g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight );
  106. SelectClipRgn( pDC->m_hDC, rgn );
  107. // Draw a higlighted background for the selected glyph
  108. {
  109. int x = g_pSelectedGylph->x;
  110. int y = g_pSelectedGylph->y;
  111. int w = g_pSelectedGylph->w;
  112. int h = g_pSelectedGylph->h;
  113. pDC->FillSolidRect( x, y, w, h, COLOR_DARKRED );
  114. }
  115. // Setup the DC for drawing text
  116. pDC->SetTextColor( COLOR_WHITE );
  117. pDC->SelectObject( g_Font.m_hFont );
  118. pDC->SetTextAlign( TA_LEFT|TA_TOP );
  119. pDC->SetMapMode( MM_TEXT );
  120. pDC->SetBkMode( TRANSPARENT );
  121. pDC->SetBkColor( COLOR_BLUE );
  122. CPen pen( PS_SOLID, 1, COLOR_RED );
  123. pDC->SelectObject( &pen );
  124. // Render the selected glyph
  125. GLYPH_ATTR* pGlyph = g_pSelectedGylph;
  126. {
  127. WCHAR c = g_cSelectedGlyph;
  128. WCHAR str[2] = L"A";
  129. str[0] = c ? c : 0xffff;
  130. if ( g_Font.m_ValidGlyphs[c] == 2 )
  131. {
  132. // Draw a square box for a placeholder for custom glyph graphics
  133. pDC->FillSolidRect( pGlyph->x, pGlyph->y, pGlyph->w, pGlyph->h, COLOR_BLACK );
  134. }
  135. else
  136. {
  137. int sx = pGlyph->x;
  138. int sy = pGlyph->y;
  139. // Adjust ccordinates to account for the leading edge
  140. if ( str[0] > 0x1000 )
  141. {
  142. }
  143. else
  144. {
  145. sx -= pGlyph->a;
  146. if ( g_Font.m_bOutlineEffect )
  147. sx -= 1;
  148. }
  149. if ( g_Font.m_bOutlineEffect )
  150. {
  151. sx++;
  152. sy++;
  153. pDC->SetTextColor( COLOR_BLACK );
  154. ExtTextOutW( pDC->m_hDC, sx-1, sy-1, ETO_OPAQUE, NULL, str, 1, NULL );
  155. ExtTextOutW( pDC->m_hDC, sx+0, sy-1, ETO_OPAQUE, NULL, str, 1, NULL );
  156. ExtTextOutW( pDC->m_hDC, sx+1, sy-1, ETO_OPAQUE, NULL, str, 1, NULL );
  157. ExtTextOutW( pDC->m_hDC, sx-1, sy+0, ETO_OPAQUE, NULL, str, 1, NULL );
  158. ExtTextOutW( pDC->m_hDC, sx+1, sy+0, ETO_OPAQUE, NULL, str, 1, NULL );
  159. ExtTextOutW( pDC->m_hDC, sx-1, sy+1, ETO_OPAQUE, NULL, str, 1, NULL );
  160. ExtTextOutW( pDC->m_hDC, sx+0, sy+1, ETO_OPAQUE, NULL, str, 1, NULL );
  161. ExtTextOutW( pDC->m_hDC, sx+1, sy+1, ETO_OPAQUE, NULL, str, 1, NULL );
  162. }
  163. if ( g_Font.m_bShadowEffect )
  164. {
  165. pDC->SetTextColor( COLOR_BLACK );
  166. ExtTextOutW( pDC->m_hDC, sx+2, sy+2, ETO_OPAQUE, NULL, str, 1, NULL );
  167. }
  168. // Output the letter
  169. pDC->SetTextColor( COLOR_WHITE );
  170. ExtTextOutW( pDC->m_hDC, sx, sy, ETO_OPAQUE, NULL, str, 1, NULL );
  171. }
  172. }
  173. // Draw a red outline around the selected glyph
  174. {
  175. // Create a red pen
  176. CPen pen( PS_SOLID, 1, COLOR_RED );
  177. pDC->SelectObject( &pen );
  178. // Draw the outline
  179. int x1 = pGlyph->x - 1;
  180. int y1 = pGlyph->y - 1;
  181. int x2 = pGlyph->x + pGlyph->w;
  182. int y2 = pGlyph->y + pGlyph->h;
  183. pDC->MoveTo( x1, y1 );
  184. pDC->LineTo( x2, y1 );
  185. pDC->LineTo( x2, y2 );
  186. pDC->LineTo( x1, y2 );
  187. pDC->LineTo( x1, y1 );
  188. }
  189. SelectClipRgn( pDC->m_hDC, NULL );
  190. DeleteObject( rgn );
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Name: OnDraw()
  194. // Desc: Overridden draw function. Draws the font glyphs if a font is loaded,
  195. // else just a black background.
  196. //-----------------------------------------------------------------------------
  197. VOID CFontMakerView::OnNewFontGlyphs()
  198. {
  199. // Select the resulting bits into our memory DC
  200. static CBitmap Bitmap;
  201. Bitmap.DeleteObject();
  202. Bitmap.CreateBitmap( g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight, 1, 32, g_Font.m_pBits );
  203. m_memDC.SelectObject( &Bitmap );
  204. // Trigger the view to be re-drawn
  205. OnUpdate(0,0,0);
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Name: OnDraw()
  209. // Desc: Overridden draw function. Draws the font glyphs if a font is loaded,
  210. // else just a black background.
  211. //-----------------------------------------------------------------------------
  212. VOID CFontMakerView::OnDraw( CDC* pDC )
  213. {
  214. RECT rc;
  215. GetClientRect( &rc );
  216. // Draw the view
  217. if ( g_Font.m_hFont == NULL && !g_Font.m_pCustomFilename )
  218. {
  219. // Don't display any scroll bars
  220. CSize sizeTotal( 0, 0 );
  221. SetScrollSizes( MM_TEXT, sizeTotal );
  222. // Draw a black background
  223. pDC->FillSolidRect( 0, 0, rc.right, rc.bottom, COLOR_BLACK );
  224. }
  225. else
  226. {
  227. // Set the scroll sizes for the view
  228. CSize sizeTotal( g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight );
  229. SetScrollSizes( MM_TEXT, sizeTotal );
  230. // Draw the view's black areas
  231. pDC->FillSolidRect( g_Font.m_dwTextureWidth, 0, max( (int)g_Font.m_dwTextureWidth, rc.right), g_Font.m_dwTextureHeight, COLOR_BLACK );
  232. pDC->FillSolidRect( 0, g_Font.m_dwTextureHeight, max( (int)g_Font.m_dwTextureWidth, rc.right), max( (int)g_Font.m_dwTextureHeight, rc.bottom), COLOR_BLACK );
  233. // Display the bitmap of all the rendered glyphs
  234. pDC->BitBlt( 0, 0, g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight, &m_memDC, 0, 0, SRCCOPY );
  235. // Draw the selected glyph, if any
  236. RenderSelectedGlyph( pDC );
  237. }
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Name: OnLButtonDown()
  241. // Desc: Overridden function to select a glyph when the user clicks the mouse.
  242. //-----------------------------------------------------------------------------
  243. void CFontMakerView::OnLButtonDown( UINT nFlags, CPoint point )
  244. {
  245. if ( !g_Font.m_hFont )
  246. return;
  247. // Correct the mouseclick point to account for the scroll position
  248. point += GetScrollPosition();
  249. // Find out which glyph, if any, is selected by the mouse click
  250. theApp.UpdateSelectedGlyph( FALSE );
  251. for( DWORD i=0; i<g_Font.m_dwNumGlyphs && g_Font.m_pGlyphs; i++ )
  252. {
  253. GLYPH_ATTR* pGlyph = &g_Font.m_pGlyphs[i];
  254. if ( point.x >= pGlyph->x-2 && point.x <= pGlyph->x + pGlyph->w )
  255. {
  256. if ( point.y >= pGlyph->y-2 && point.y <= pGlyph->y + pGlyph->h )
  257. {
  258. theApp.UpdateSelectedGlyph( TRUE, i );
  259. break;
  260. }
  261. }
  262. }
  263. // Redraw the view to show the newly selected glyph
  264. Invalidate( TRUE );
  265. // Call the base class' handler
  266. CScrollView::OnLButtonDown( nFlags, point );
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Name: OnKeyDown()
  270. // Desc: Overridden function to select a glyph with the keyboard.
  271. //-----------------------------------------------------------------------------
  272. void CFontMakerView::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
  273. {
  274. if ( !g_Font.m_hFont )
  275. return;
  276. if( g_Font.m_dwNumGlyphs > 0 )
  277. {
  278. if( FALSE == g_bIsGlyphSelected )
  279. {
  280. if( nChar == 37 || nChar == 38 || nChar == 39 || nChar == 40 ) // Left, right, up or down
  281. {
  282. // Select the first glyph
  283. theApp.UpdateSelectedGlyph( TRUE, 0 );
  284. }
  285. }
  286. else
  287. {
  288. if( nChar == 37 ) // Left
  289. theApp.UpdateSelectedGlyph( TRUE, max( 0, g_iSelectedGlyphNum-1 ) );
  290. else if( nChar == 39 ) // Right
  291. theApp.UpdateSelectedGlyph( TRUE, min( (int)g_Font.m_dwNumGlyphs-1, g_iSelectedGlyphNum+1 ) );
  292. else if( nChar == 38 || nChar == 40 ) // Up or down
  293. {
  294. // Find the closest glyph above or below to move to
  295. int x = g_pSelectedGylph->x + g_pSelectedGylph->w/2;
  296. int y = g_pSelectedGylph->y + g_pSelectedGylph->h/2;
  297. if( nChar == 38 ) y -= g_pSelectedGylph->h;
  298. if( nChar == 40 ) y += g_pSelectedGylph->h;
  299. for( DWORD i=0; i<g_Font.m_dwNumGlyphs; i++ )
  300. {
  301. GLYPH_ATTR* pGlyph = &g_Font.m_pGlyphs[i];
  302. if( x >= pGlyph->x-2 && x <= pGlyph->x + pGlyph->w )
  303. {
  304. if( y >= pGlyph->y-2 && y <= pGlyph->y + pGlyph->h )
  305. {
  306. theApp.UpdateSelectedGlyph( TRUE, i );
  307. break;
  308. }
  309. }
  310. }
  311. }
  312. else if ( nChar == 46 )
  313. {
  314. // delete a glyph
  315. theApp.OnGlyphsCustom();
  316. // mark glyph as invalid
  317. g_Font.DeleteGlyph( g_cSelectedGlyph );
  318. // reset to the first glyph
  319. theApp.UpdateSelectedGlyph( FALSE );
  320. }
  321. else if ( nChar == 45 )
  322. {
  323. // insert a glyph
  324. theApp.OnGlyphsCustom();
  325. // reset to the first glyph
  326. theApp.UpdateSelectedGlyph( FALSE );
  327. theApp.InsertGlyph();
  328. }
  329. }
  330. // Redraw the view to show the newly selected glyph
  331. Invalidate( TRUE );
  332. }
  333. CScrollView::OnKeyDown( nChar, nRepCnt, nFlags );
  334. }