Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / multimedia / OpenGL

OAG Library (OpenGL) Part 2.2 - Drawing 2D Texts Using the Mouse and Programatically

4.00/5 (4 votes)
23 Oct 2010CPOL2 min read 31.1K   1.1K  
This tutorial shows library code for 2D Texts and how to draw them programatically using the mouse in an MFC application.

Introduction

In this tutorial, we will see how to draw 2D fonts. You must download the library to compile the sample. Click here to go to the download page. Using OAG_2D, you can save and open XML files (*.oagxml).

Drawing 2D Fonts

To draw fonts using the library, you need to create an instance of oag::FontMappingTable to store a font and an instance of oag::OAGFontMapping2D. The class oag::FontMappingTable manages the fonts used to draw. Once you choose a font and stores it in the class oag::FontMappingTable, it is added in an array list of fonts in the class oag::FontMappingTable. The class oag::OAGFontMapping2D is used to draw the texts using a font stored in the class oag::FontMappingTable.

Setting up the Document Class

Members for the document:

C++
oag::ObjectsMappingTable*    pObjectsMappingTable;
oag::OAGScene*            m_pScene;

Operations for the document:

C++
void CreateLibraryObjects();
void UnloadLibraryObjects();

Constructor and destructor:

C++
COAGMFCDoc::COAGMFCDoc()
:m_pScene(NULL)
,m_pObjectsMappingTable(NULL)
{
  CreateLibraryObjects();
}
 
COAGMFCDoc::~COAGMFCDoc()
{
   UnloadLibraryObjects();
}

void COAGMFCDoc::CreateLibraryObjects()
{
  if( m_pObjectsMappingTable == NULL)
     m_pObjectsMappingTable = new oag::ObjectsMappingTable();

  if( m_pScene == NULL )
  {
     m_pScene = new oag::OAGScene();
     m_pScene->SetFontMappingTable(  m_pObjectsMappingTable->GetFontMappingTable() );
     m_pScene->SetTextureMappingTable( m_pObjectsMappingTable->GetTextureMappingTable() );
  }
}

void COAGMFCDoc::UnloadLibraryObjects()
{
   //Deletes the scene and all objects from the memory
   if ( m_pScene )
   {
     m_pScene->DeleteAllObjects();

     delete m_pScene;
     m_pScene = NULL;
   }

   if ( m_pObjectsMappingTable )
   {
	   delete m_pObjectsMappingTable;
      m_pObjectsMappingTable = NULL;
   }
}

When a new document is created, we need to delete all the objects and create them again:

C++
BOOL COAGMFCDoc::OnNewDocument()
{
  if (!CDocument::OnNewDocument())
   return FALSE;
 
  //Deleting all library objects when a new document is started.
  //The Fonts must be deleted and created again,
  //if not they are not drawn properly
  UnloadLibraryObjects();
  CreateLibraryObjects();
    
  UpdateAllViews(NULL);
 
  return TRUE;
}

Inserting a Font

To insert a font, click on the TableObjects menu, click on Font, and choose a true type type font.

Image 1

After choosing the a font, it is created with a size of 24. The function pFont->SetFontSize(24) does this. You do not need this font again to draw a 2D text, you just get this font from m_pFontMappingTable and uses it to draw 2D texts:

C++
void COAGMFCDoc::OnInsertFont()
{
  CString filter;
  filter.LoadString( IDS_FONT_FILTER );
 
  CFileDialog dlg(TRUE, "*.ttf", NULL, 
                  OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST, filter );
 
  if(dlg.DoModal() == IDOK)
  {
   CString strFileName = dlg.GetPathName().GetString();
 
   POSITION pos = GetFirstViewPosition();
   COAGMFCView* pView =  (COAGMFCView*) GetNextView(pos);
 
   if ( pView->m_pWinGraphicContext->MakeCurrent() )
   {
    oag::OAGFont* pFont = oag::OAGFontLoader::LoadFontFromDisk( 
                            strFileName.GetString(), OAG_FONT_MAP_2D );
 
    if( pFont )
    {
      pFont->SetFontSize(24);
      pFont->SetFontName("arial");
      if ( pFontMapTable == NULL || 
          !m_pObjectsMappingTable->GetFontMappingTable()->AddFont( pFont ) )
         delete pFont;
      else
         pFontMapTable->AddFont( pFont );
    }
    pView->m_pWinGraphicContext->DeleteCurrent();
   }
  }
}

Inserting a 2D Text

To insert a 2D text, select the Draw menu, click on 2DText, and click on the screen to insert a text:

Image 2

Code to Insert a 2D Text

The function font2d->SetText sets a text to draw on screen, and font2d->SetPosition sets the text position on the screen. The function font2d->SetFontNameReference is used to get the current font set when you save to an XML file. If font2d->SetFontNameReference is not used, when you read an XML file, the font is not set and no text is drawn on the screen.

C++
void CText2DTool::AddAllVerticesToScene()
{
   oag::OAGFontMapping2D* font2d = new oag::OAGFontMapping2D(); 
 
   if( m_pScene->GetFontMappingTable()->m_ListFont.size() > 0 )
   {
     font2d->SetFont( m_pScene->GetFontMappingTable()->m_ListFont[0]->GetFont() );
     font2d->SetFontNameReference ( 
        m_pScene->GetFontMappingTable()->m_ListFont[0]->GetFontName() );
   }    
 
   oag::OAGVector3f vec = m_arrVector[0];
   font2d->SetText("Example of 2DText"); 
   font2d->SetPosition( oag::OAGVector3f( vec.m_X, vec.m_Y, vec.m_Z ) ); 
   m_pScene->AddObject( font2d );
 
}
 
void CText2DTool::OnMouseClick(oag::OAGVector3f& ptMouse)
{
  switch( m_nStep )
  {
   case 0:
   {
     m_arrVector.Add( ptMouse );
     AddAllVerticesToScene();
     CTool::OnFinalize();
    }
    break;
   }
}

The XML File

In the XML below, the node Tables stores a node Fonts. The node Fonts stores the fonts used to draw the texts. For this sample, we used arial.tff with size 24. The node <Font Name="" FileName="arial.ttf" Size="24."/> shows this.

The node Objects stores the 2D text to draw on the screen. The node Text2D shows this:

XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<OAGLibrary>
  <Tables>
    <Fonts>
      <Font Name="arial" FileName="arial.ttf" Size="24."/>
    </Fonts>
  </Tables>
  <Scene Type="Draw">
    <Objects>
      <Text2D Name="">
        <UseFont Name="arial"/>
        <String Value="Example of 2DText"/>
        <Color Red="1." Green="1." Blue="1." Alpha="1."/>
        <Transform>
          <Translation x="161." y="148." z="0."/>
          <Scale x="1." y="1." z="1."/>
          <Rotation x="0." y="0." z="0."/>
        </Transform>
      </Text2D>
    </Objects>
  </Scene>
</OAGLibrary>

Class oag::Font

C++
class OAGFont
{
    public:
        OAGFont(void);
        virtual ~OAGFont(void);
 
    //Attributes
    protected:
        bool                m_bIsDone;
        int                    m_nFontSize;
        OAG_FONT_MAPPING    m_enumFontMapping;
        FTFont*                m_pFont;
 
        std::string            m_strName;
        std::string            m_strFolderPath, m_strFilename;
 
 
    //Operations
    public:
        
        //Gets the FileName used by the font
        std::string GetFileName()
        {
            return m_strFilename;
        }
 
        FTFont* GetFont()
        {
            return m_pFont;
        }
 
        int GetFontSize()
        {
            return m_nFontSize;
        }
            
        //Gets the current name set for the texture
        std::string GetFontName()
        { 
            return m_strName; 
        }
 
 
        //Sets the Font Size
    
        void SetFontSize(int nFontSize)
        {
            int newSize = nFontSize;
            if ( m_pFont )
            {
                if ( m_pFont->FaceSize( newSize ) )
                    m_nFontSize = nFontSize;
            }
        }
 
        //Sets a for the object
        void SetFontName(std::string strName)
        {
            m_strName = strName; 
        }
 
        void SetIOSystemFilter(std::string folderPath, std::string fileName)
        {
            m_strFolderPath = folderPath;
            m_strFilename = fileName;
        }
 
 
        //bool IsInitialized()    { return m_bIsInitialized; };
 
    //Virtual
    public:
        virtual void LoadFontFromDisk(std::string strFileName){}
    };
    
//Constructor
oag::OAGFont::OAGFont(void)
:m_bIsDone(false)
,m_pFont(NULL)
,m_nFontSize(10)
{
}
 
//Destructor
oag::OAGFont::~OAGFont(void)
{
    if( m_pFont )
    {
        delete m_pFont;
        m_pFont = NULL;
    }
}

Class oag::OAGFontMapping

C++
class OAGFontMapping : public oag::OAGObject
{
    public:
        OAGFontMapping(void);
        virtual ~OAGFontMapping(void);
 
    //Attributes
    protected:
        std::string        m_strText;
        FTFont*            m_pFont;
        std::string        m_strFontNameReference;
    
    //Operations
    public:
        std::string GetText()
        {
            return m_strText;
        }
 
        void SetFontNameReference(std::string strFontNameReference)
        {
            m_strFontNameReference = strFontNameReference;
        }
 
        void SetText(std::string strText)
        { 
            m_strText = strText;
        }
 
        void SetFont(FTFont* pFont)
        {
            m_pFont = pFont;
        }
    //Virtual
    public:
        virtual    void OnDraw(){};
        virtual void ReadNodeXML(CXmlNode* pNode);
        virtual void SaveNodeXML(CXmlNode* pNode);
};

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)