This page describes briefly how to add a new font type to wxArt2D. The majority of this page is some fundamental code. It is mainly documented here, because, the font class is used in some other places, where it should be added by hand.
This document might become outdated. Although it is assumed the general trend will be the same, details might changed, so please also check the source code of eg. the Stroke fonts.
Unfortunately, at present a new font cannot be created separately from the library, since adding a new font type, involves changing some routines in the library itself.
It is assumed, that you want to add a font format named monkey.
Class definition.
The class definition itself is pretty straightforward. The next example shows a typical font class definition.
class a2dFontMonkey
{
public:
a2dFontMonkey(const wxString& filename = wxT(""), double size = 0.0 );
a2dFontMonkey(const a2dFontMonkey& other);
a2dFontMonkey( const a2dFontMonkey& other, CloneOptions options );
virtual ~a2dFontMonkey();
virtual wxRefObject* Clone( CloneOptions options ) const;
a2dFontMonkey& operator = (const a2dFontMonkey& other);
wxString
GetFilename(
bool filenameonly =
false )
const;
virtual double GetWidth( wxChar c )
const;
virtual double GetKerning( wxChar c1, wxChar c2 )
const;
protected:
wxString m_filename;
private:
DECLARE_DYNAMIC_CLASS(a2dFontMonkey)
};
Class implementation.
The class implementation is also straightforward.
The problem you have to deal with is parsing the font. Also for improved drawing speed, you might want to add some font caching here. (see also the implementation of a2dFontFreetype::GetGlyph )
The extra parameter of m_fontinfo is free to use for anything, but please keep in mind, that this should allways be in text format. In general it will be used for storing the filename of the font. (see also a2dFontInfo )
IMPLEMENT_DYNAMIC_CLASS( a2dFontMonkey,
a2dFont )
a2dFontMonkey::a2dFontMonkey(const wxString& filename, double size, int alignment)
{
m_fontinfo.SetType( wxT("Monkey font") );
SetFilename( filename );
}
a2dFontMonkey::a2dFontMonkey( const a2dFontMonkey& other )
{
m_fontinfo.SetType( wxT("Monkey font") );
m_width = NULL;
m_characters = NULL;
m_weight = -1;
*this = other;
}
a2dFontMonkey::a2dFontMonkey( const a2dFontMonkey& other, CloneOptions options )
{
m_width = NULL;
m_characters = NULL;
m_weight = -1;
SetFilename( other.m_filename );
}
a2dFontMonkey::~a2dFontMonkey()
{
delete .......
}
wxRefObject* a2dFontMonkey::Clone( CloneOptions options ) const
{
return new a2dFontMonkey( *this, options );
}
a2dFontMonkey& a2dFontMonkey::operator = ( const a2dFontMonkey& other )
{
a2dFont::operator = ( other );
SetFilename( m_filename );
return *this;
}
bool a2dFontMonkey::operator == (
const a2dFont& other )
const
{
&& ( m_filename == mkyfont->m_filename );
}
wxString a2dFontMonkey::GetFilename(bool filenameonly) const
{
if ( filenameonly )
{
wxFileName filename( m_filename );
return filename.GetFullName();
}
else
return m_filename;
}
void a2dFontMonkey::SetFilename(const wxString& filename)
{
m_ok = false;
delete .......
m_filename = filename;
if ( m_filename.IsEmpty() )
return;
wxString fname =
a2dCanvasGlobals->GetFontPathList().FindValidPath( m_filename );
...........
size = ......
m_height = .... / size;
m_desc = .... / size;
m_lead = ..... / size;
m_ok = true;
}
double a2dFontMonkey::GetWidth( wxChar c ) const
{
if ( !m_ok )
return 0.0;
return m_size * .....
}
double a2dFontMonkey::GetKerning( wxChar c1, wxChar c2 ) const
{
if ( !m_ok )
return 0.0;
return m_size * .....
}
{
for ( wxPathList::Node *node = pathlist.GetFirst(); node; node = node->GetNext() )
{
wxString path(node->GetData());
if (!wxDir::Exists( path ) )
continue;
wxArrayString files;
wxDir::GetAllFiles( path, &files, wxT("*.mky"), wxDIR_FILES );
for ( unsigned int i = 0; i < files.GetCount(); i++)
{
wxFileName filename( files.Item(i) );
wxString fontname = ....
wxString stylename = ....
wxT("Monkey font"), fontname, stylename, filename.GetFullName() ));
}
}
}
{
{
a2dFontMonkey* font =
new a2dFontMonkey( info.
GetExtra(),
info.
GetSize(), info.GetAlignment() );
return font;
}
else
return NULL;
}
More things to do.
Now that we have a font class, with some a Createfont class does not mean, that the font can now be created in a general way. The applications, do not know of the existance of specific font classes. Therefore they will call a2dFont::CreateFont. To enable the creation of your font, you should add this method to
- (stylebase.cpp) a2dFont* a2dFont::CreateFont( const a2dFontInfo& info );
Also to be able to select the font using the font selection dialog, add your class to:
Drawing of the font
Add a specific monkey font drawing routines to the wxDrawer2D header:
- (drawer2d.h) virtual void wxDrawer2D::DrawTextMonkey( const wxString& text, double x, double y ) { DrawTextGeneric( text, x, y, &wxDcDrawer::DrawCharMonkeyCb ); }
- (drawer2d.h) virtual void wxDrawer2D::DrawCharMonkey( wxChar c ) { DrawCharUnknown( c ); }
- (drawer2d.h) void wxDrawer2D::DrawCharMonkeyCb( wxChar c ) { DrawCharMonkey( c ); }
The last line is a wrapper for the DrawChar function. It seems redundant, but Iso C++ does not allow anymore to call a virtual member directly.
The font drawing will be invokated through DrawText. To let this know of the existance of the monkey font class, you should add this newly created method to:
- (drawer2d.cpp) void wxDrawer2D::DrawText( const wxString& text, double x, double y );
Now, at minimum, implement the font drawing in wxDcDrawer.
The drawing routines are seperated in two routines. The first parses the string and calls the second one to draw each character. The first is allready supplied, but might be overruled, to set text colours, etc.
void wxDrawer2D::DrawTextMonkey( const wxString& text, double x, double y )
{
...
DrawTextGeneric( text, x, y, (void (wxDrawer2D::*)( wxChar )) &wxDcDrawer::DrawCharMonkeyCb );
}
The implementation of the character drawing routine can fully concentrate on drawing the character. The calling routine allready took care of performing all necessary affine transforms. The origin (0, 0) is set at the lower left bounding box of the character. Depending on the font, scaling to size should still be performed here.
void wxDcDrawer::DrawCharMonkey( wxChar c )
{
affine.
Scale( mkyfont->GetSize() );
SetTransForm( oldaffine * affine );
SetTransForm( oldaffine );
}
So now finally the font should work.