hl2_src-leak-2017/src/utils/xbox/FontMaker/fontmakerwnd.cpp

397 lines
13 KiB
C++

//-----------------------------------------------------------------------------
// Name: FontMakerWnd.cpp
//
// Desc: The window and scroll view class for the fontmaker app
//
// Hist: 09.06.02 - Revised Fontmaker sample
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "FontMaker.h"
#include "Glyphs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CTextureFont g_Font;
BOOL g_bIsGlyphSelected = FALSE;
int g_iSelectedGlyphNum = 0;
WCHAR g_cSelectedGlyph = '\0';
GLYPH_ATTR* g_pSelectedGylph = NULL;
// Colors
#define COLOR_WHITE ( RGB(255,255,255) )
#define COLOR_BLACK ( RGB( 0, 0, 0) )
#define COLOR_BLUE ( RGB( 0, 0,255) )
#define COLOR_RED ( RGB(255, 0, 0) )
#define COLOR_DARKRED ( RGB(128, 0, 0) )
//-----------------------------------------------------------------------------
// CFontMakerFrameWnd
//-----------------------------------------------------------------------------
IMPLEMENT_DYNCREATE(CFontMakerFrameWnd, CFrameWnd)
BEGIN_MESSAGE_MAP(CFontMakerFrameWnd, CFrameWnd)
//{{AFX_MSG_MAP(CFontMakerFrameWnd)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
int CFontMakerFrameWnd::OnCreate( LPCREATESTRUCT pCreateStruct )
{
if( CFrameWnd::OnCreate( pCreateStruct ) == -1 )
return -1;
// Create a docked dialog bar
EnableDocking( CBRS_ALIGN_ANY );
if( !m_wndDialogBar.Create( this, IDD_DIALOGBAR,
CBRS_LEFT, IDD_DIALOGBAR ) )
{
TRACE0("Failed to create DlgBar\n");
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// CFontMakerView
//-----------------------------------------------------------------------------
IMPLEMENT_DYNCREATE(CFontMakerView, CScrollView)
BEGIN_MESSAGE_MAP(CFontMakerView, CScrollView)
//{{AFX_MSG_MAP(CFontMakerView)
ON_WM_LBUTTONDOWN()
ON_WM_ERASEBKGND()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
// Name: ~CFontMakerView()
// Desc: Destructor with special cleanup
//-----------------------------------------------------------------------------
CFontMakerView::~CFontMakerView()
{
// Cleanup before exitting
m_memDC.DeleteDC();
}
//-----------------------------------------------------------------------------
// Name: OnInitialUpdate()
// Desc: Called when the view is created.
//-----------------------------------------------------------------------------
void CFontMakerView::OnInitialUpdate()
{
// Set the scroll bars
CScrollView::OnInitialUpdate();
CSize szTotal( g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight );
SetScrollSizes( MM_TEXT, szTotal );
CPoint ptCenter( 0, 0 );
CenterOnPoint( ptCenter );
// Create a secondary DC, used for drawing
m_memDC.CreateCompatibleDC( GetDC() );
}
//-----------------------------------------------------------------------------
// Name: OnEraseBkgnd()
// Desc: Overridden function to prevent the view from flickering during resizes
// and redraws
//-----------------------------------------------------------------------------
BOOL CFontMakerView::OnEraseBkgnd( CDC* pDC )
{
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: RenderSelectedGlyph()
// Desc: Highlight the selected glyph
//-----------------------------------------------------------------------------
VOID RenderSelectedGlyph( CDC* pDC )
{
// If no glyph is selected, return
if( FALSE == g_bIsGlyphSelected )
return;
HRGN rgn = CreateRectRgn( 0, 0, g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight );
SelectClipRgn( pDC->m_hDC, rgn );
// Draw a higlighted background for the selected glyph
{
int x = g_pSelectedGylph->x;
int y = g_pSelectedGylph->y;
int w = g_pSelectedGylph->w;
int h = g_pSelectedGylph->h;
pDC->FillSolidRect( x, y, w, h, COLOR_DARKRED );
}
// Setup the DC for drawing text
pDC->SetTextColor( COLOR_WHITE );
pDC->SelectObject( g_Font.m_hFont );
pDC->SetTextAlign( TA_LEFT|TA_TOP );
pDC->SetMapMode( MM_TEXT );
pDC->SetBkMode( TRANSPARENT );
pDC->SetBkColor( COLOR_BLUE );
CPen pen( PS_SOLID, 1, COLOR_RED );
pDC->SelectObject( &pen );
// Render the selected glyph
GLYPH_ATTR* pGlyph = g_pSelectedGylph;
{
WCHAR c = g_cSelectedGlyph;
WCHAR str[2] = L"A";
str[0] = c ? c : 0xffff;
if ( g_Font.m_ValidGlyphs[c] == 2 )
{
// Draw a square box for a placeholder for custom glyph graphics
pDC->FillSolidRect( pGlyph->x, pGlyph->y, pGlyph->w, pGlyph->h, COLOR_BLACK );
}
else
{
int sx = pGlyph->x;
int sy = pGlyph->y;
// Adjust ccordinates to account for the leading edge
if ( str[0] > 0x1000 )
{
}
else
{
sx -= pGlyph->a;
if ( g_Font.m_bOutlineEffect )
sx -= 1;
}
if ( g_Font.m_bOutlineEffect )
{
sx++;
sy++;
pDC->SetTextColor( COLOR_BLACK );
ExtTextOutW( pDC->m_hDC, sx-1, sy-1, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx+0, sy-1, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx+1, sy-1, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx-1, sy+0, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx+1, sy+0, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx-1, sy+1, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx+0, sy+1, ETO_OPAQUE, NULL, str, 1, NULL );
ExtTextOutW( pDC->m_hDC, sx+1, sy+1, ETO_OPAQUE, NULL, str, 1, NULL );
}
if ( g_Font.m_bShadowEffect )
{
pDC->SetTextColor( COLOR_BLACK );
ExtTextOutW( pDC->m_hDC, sx+2, sy+2, ETO_OPAQUE, NULL, str, 1, NULL );
}
// Output the letter
pDC->SetTextColor( COLOR_WHITE );
ExtTextOutW( pDC->m_hDC, sx, sy, ETO_OPAQUE, NULL, str, 1, NULL );
}
}
// Draw a red outline around the selected glyph
{
// Create a red pen
CPen pen( PS_SOLID, 1, COLOR_RED );
pDC->SelectObject( &pen );
// Draw the outline
int x1 = pGlyph->x - 1;
int y1 = pGlyph->y - 1;
int x2 = pGlyph->x + pGlyph->w;
int y2 = pGlyph->y + pGlyph->h;
pDC->MoveTo( x1, y1 );
pDC->LineTo( x2, y1 );
pDC->LineTo( x2, y2 );
pDC->LineTo( x1, y2 );
pDC->LineTo( x1, y1 );
}
SelectClipRgn( pDC->m_hDC, NULL );
DeleteObject( rgn );
}
//-----------------------------------------------------------------------------
// Name: OnDraw()
// Desc: Overridden draw function. Draws the font glyphs if a font is loaded,
// else just a black background.
//-----------------------------------------------------------------------------
VOID CFontMakerView::OnNewFontGlyphs()
{
// Select the resulting bits into our memory DC
static CBitmap Bitmap;
Bitmap.DeleteObject();
Bitmap.CreateBitmap( g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight, 1, 32, g_Font.m_pBits );
m_memDC.SelectObject( &Bitmap );
// Trigger the view to be re-drawn
OnUpdate(0,0,0);
}
//-----------------------------------------------------------------------------
// Name: OnDraw()
// Desc: Overridden draw function. Draws the font glyphs if a font is loaded,
// else just a black background.
//-----------------------------------------------------------------------------
VOID CFontMakerView::OnDraw( CDC* pDC )
{
RECT rc;
GetClientRect( &rc );
// Draw the view
if ( g_Font.m_hFont == NULL && !g_Font.m_pCustomFilename )
{
// Don't display any scroll bars
CSize sizeTotal( 0, 0 );
SetScrollSizes( MM_TEXT, sizeTotal );
// Draw a black background
pDC->FillSolidRect( 0, 0, rc.right, rc.bottom, COLOR_BLACK );
}
else
{
// Set the scroll sizes for the view
CSize sizeTotal( g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight );
SetScrollSizes( MM_TEXT, sizeTotal );
// Draw the view's black areas
pDC->FillSolidRect( g_Font.m_dwTextureWidth, 0, max( (int)g_Font.m_dwTextureWidth, rc.right), g_Font.m_dwTextureHeight, COLOR_BLACK );
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 );
// Display the bitmap of all the rendered glyphs
pDC->BitBlt( 0, 0, g_Font.m_dwTextureWidth, g_Font.m_dwTextureHeight, &m_memDC, 0, 0, SRCCOPY );
// Draw the selected glyph, if any
RenderSelectedGlyph( pDC );
}
}
//-----------------------------------------------------------------------------
// Name: OnLButtonDown()
// Desc: Overridden function to select a glyph when the user clicks the mouse.
//-----------------------------------------------------------------------------
void CFontMakerView::OnLButtonDown( UINT nFlags, CPoint point )
{
if ( !g_Font.m_hFont )
return;
// Correct the mouseclick point to account for the scroll position
point += GetScrollPosition();
// Find out which glyph, if any, is selected by the mouse click
theApp.UpdateSelectedGlyph( FALSE );
for( DWORD i=0; i<g_Font.m_dwNumGlyphs && g_Font.m_pGlyphs; i++ )
{
GLYPH_ATTR* pGlyph = &g_Font.m_pGlyphs[i];
if ( point.x >= pGlyph->x-2 && point.x <= pGlyph->x + pGlyph->w )
{
if ( point.y >= pGlyph->y-2 && point.y <= pGlyph->y + pGlyph->h )
{
theApp.UpdateSelectedGlyph( TRUE, i );
break;
}
}
}
// Redraw the view to show the newly selected glyph
Invalidate( TRUE );
// Call the base class' handler
CScrollView::OnLButtonDown( nFlags, point );
}
//-----------------------------------------------------------------------------
// Name: OnKeyDown()
// Desc: Overridden function to select a glyph with the keyboard.
//-----------------------------------------------------------------------------
void CFontMakerView::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
{
if ( !g_Font.m_hFont )
return;
if( g_Font.m_dwNumGlyphs > 0 )
{
if( FALSE == g_bIsGlyphSelected )
{
if( nChar == 37 || nChar == 38 || nChar == 39 || nChar == 40 ) // Left, right, up or down
{
// Select the first glyph
theApp.UpdateSelectedGlyph( TRUE, 0 );
}
}
else
{
if( nChar == 37 ) // Left
theApp.UpdateSelectedGlyph( TRUE, max( 0, g_iSelectedGlyphNum-1 ) );
else if( nChar == 39 ) // Right
theApp.UpdateSelectedGlyph( TRUE, min( (int)g_Font.m_dwNumGlyphs-1, g_iSelectedGlyphNum+1 ) );
else if( nChar == 38 || nChar == 40 ) // Up or down
{
// Find the closest glyph above or below to move to
int x = g_pSelectedGylph->x + g_pSelectedGylph->w/2;
int y = g_pSelectedGylph->y + g_pSelectedGylph->h/2;
if( nChar == 38 ) y -= g_pSelectedGylph->h;
if( nChar == 40 ) y += g_pSelectedGylph->h;
for( DWORD i=0; i<g_Font.m_dwNumGlyphs; i++ )
{
GLYPH_ATTR* pGlyph = &g_Font.m_pGlyphs[i];
if( x >= pGlyph->x-2 && x <= pGlyph->x + pGlyph->w )
{
if( y >= pGlyph->y-2 && y <= pGlyph->y + pGlyph->h )
{
theApp.UpdateSelectedGlyph( TRUE, i );
break;
}
}
}
}
else if ( nChar == 46 )
{
// delete a glyph
theApp.OnGlyphsCustom();
// mark glyph as invalid
g_Font.DeleteGlyph( g_cSelectedGlyph );
// reset to the first glyph
theApp.UpdateSelectedGlyph( FALSE );
}
else if ( nChar == 45 )
{
// insert a glyph
theApp.OnGlyphsCustom();
// reset to the first glyph
theApp.UpdateSelectedGlyph( FALSE );
theApp.InsertGlyph();
}
}
// Redraw the view to show the newly selected glyph
Invalidate( TRUE );
}
CScrollView::OnKeyDown( nChar, nRepCnt, nFlags );
}