//////////////////////////////////////////////////////////////////////////////////
// $Source: /cvsroot/cdx/cdx3.0/addons/CDXBitmapMenu/cdxbitmapfont.cpp,v $
// $Author: hebertjo $
//
// $Log: cdxbitmapfont.cpp,v $
// Revision 1.1.1.1  2000/04/22 16:50:59  hebertjo
// Initial checkin of v3.0 to SourceForge CVS.
//
// Revision 1.1.1.1  1999/05/04 23:59:24  bsimser
// Imported addons
//
// $Revision: 1.1.1.1 $
//////////////////////////////////////////////////////////////////////////////////

//
//Notes:  
//        The bitmap is a single horizontal line of characters.  Any of the 
//        first 128 characters are supported in the kerning file format.  Only the
//        characters wanted are required to be in this bitmap.  This way you can support
//        only all upper or lower case, numbers, symbols, etc, either all together or 
//        separately.  The height of the font is the height of the bitmap.  The widths
//        are specified in a kerning file.  The kerning file must match the bitmap.  
//        Loading the kerning file is done in 2 ways.  As a separate binary file or attached
//        to the end of the bitmap.  The file format of the kerning file, is KRN1 as the
//        first 4 bytes, followed by 128 bytes.  Each of the 128 bytes represents the width
//        of the ascii character with the same index.  0-127.  32 = space, 65 = A, 97 = a, etc.
//        If you don't have that character in your bitmap, supply a 0 (zero) width which
//        tells us not to process that character since it doesnt exist in the bitmap.  
//        
//        In the constructor of CDXBitmapFont is supplied the bitmap file.  After reading the
//        bitmap the constructor attempts to find the kerning table attached to the end of the file.
//        If it exists, we load it.  Otherwise the internal tables are cleared.  Afterwards, you
//        can call LoadKernelTable( filename ); which will replace the internal tables with 
//        the contents of this file.  If this file is invalid, the internal tables are cleared also.

#include "cdx.h"
#include "cdxbitmap.h"

#include <io.h> // required for the CreateFile, GetFileSize, SetFilePointer, Readfile set of commands.

#define	MAKE_ID(a, b, c, d)	(((long)(a)) | ((long)(b) << 8) | ((long)(c) << 16) | ((long)(d) << 24))


//////////////////////////////////////////////////////////////
//   CDXBitmapFont Class Constructor
// Function name : CDXBitmapFont::CDXBitmapFont : CDXSurface
// Description   : Load the bitmap and then load the kernel data if any is attached to bitmap.
//////////////////////////////////////////////////////////////
CDXBitmapFont::CDXBitmapFont(CDXScreen *pScreen, const char* szFilename, BOOL memoryType) : 
                CDXSurface(pScreen, szFilename, memoryType)
{
    //clear out widths in case file has problems
    ZeroMemory(m_cWidths, sizeof(m_cWidths));
    ZeroMemory(m_iXOffset, sizeof(m_iXOffset));

    //Using Win32 file operations, we open the file, get file size, seek to end of file, and backup length of kernel table
    HANDLE file = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD len = GetFileSize(file, NULL);
    DWORD dwFP = SetFilePointer( file, len - (sizeof(m_cWidths)+4), NULL, FILE_BEGIN);
    if(dwFP != -1)
    {
        DWORD id = 0;
        DWORD bytesread = 0;
        //read in the header, if KRN1, then read in the data.
        ReadFile(file, &id, sizeof(id), &bytesread, NULL);
        if(id == MAKE_ID('K', 'R', 'N', '1')) //kernel data version 1.0
        {
            ReadFile(file, &m_cWidths, 128, &bytesread, NULL);
        }
    }
    
    CloseHandle(file);

    int i;
    int cntr = 0;
    //loop through all the widths
    for(i=0; i<sizeof(m_cWidths); i++)
    {
        if(m_cWidths[i])    //if there is at least 1 pixel width, store xoffset
        {
            m_iXOffset[i] = cntr;   //store xoffset position
            cntr += m_cWidths[i];   //increment counter with new width
        }
        else
            m_iXOffset[i] = 0;      //clear xoffset (disable)
    }
}


//////////////////////////////////////////////////////////////
//   CDXBitmapFont Class Destructor
// Function name : CDXBitmapFont::~CDXBitmapFont
// Description   : Does nothing
//////////////////////////////////////////////////////////////
CDXBitmapFont::~CDXBitmapFont()
{

}


//////////////////////////////////////////////////////////////
// Function name : CDXBitmapFont::LoadKernelTable
// Description   : This will load a separate file as the kernel table.
//                  Obsolete if using the kernel table attached to bitmap.
//////////////////////////////////////////////////////////////
CDXBitmapFont::LoadKernelTable( const char *szFilename )
{
    //clear out widths in case file has problems
    ZeroMemory(m_cWidths, sizeof(m_cWidths));
    ZeroMemory(m_iXOffset, sizeof(m_iXOffset));
    
    DWORD id = 0;
    DWORD bytesread = 0;

    // Open the file for reading, check for file header KRN1, and read in data.
    HANDLE file = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    ReadFile(file, &id, sizeof(id), &bytesread, NULL);
    if(id == MAKE_ID('K', 'R', 'N', '1')) //kernel data version 1.0
    {
        ReadFile(file, &m_cWidths, 128, &bytesread, NULL);
    }
    CloseHandle(file);

    int i;
    int cntr = 0;
    //loop through all the widths
    for(i=0; i<sizeof(m_cWidths); i++)
    {
        if(m_cWidths[i])    //if there is at least 1 pixel width, store xoffset
        {
            m_iXOffset[i] = cntr;   //store xoffset position
            cntr += m_cWidths[i];   //increment counter with new width
        }
        else
            m_iXOffset[i] = 0;      //clear xoffset (disable)
    }
}



//////////////////////////////////////////////////////////////
// Function name : CDXBitmapFont::Print
// Description   : Display string at x,y position on specified surface
//////////////////////////////////////////////////////////////
CDXBitmapFont::Print(CDXSurface* lpDDS, int x, int y, const char *string, ... )
{
    char newstring[MAX_PATH];

	// format the message
    va_list args; // create variable list
    va_start( args, string);  // the name of the first variable is "Message"
    vsprintf( newstring, string, args); // Store the formatted string with vars in S 
    va_end( args); // end of argument list

	int len = strlen(newstring);
	int cntr;
	char let;

    // loop for the number of characters in string
	for(cntr = 0; cntr<len; cntr++)
	{
		let = newstring[cntr];  // get the current let in string to draw.
        
        // set the source rectangle and destination rectangle
        SetSrc(0, m_iXOffset[let], m_PixelHeight, m_iXOffset[let] + m_cWidths[let]);
        SetDest(y, x, y+m_PixelHeight, x+m_cWidths[let]);
        
        // draw transparent
        // ** Note: maybe later we accept BLTing flag
		DrawTrans( x, y, lpDDS);

        // increment x position by this letters width so that next letter is right beside it.
        x+=m_cWidths[let];
	}
}



//////////////////////////////////////////////////////////////
// Function name : CDXBitmapFont::GetTextExtent
// Description   : Like the GDI function, returns width and height 
//                  of string using associated bitmap font
//////////////////////////////////////////////////////////////
SIZE CDXBitmapFont::GetTextExtent(const char *string, ... )
{
    char newstring[MAX_PATH];

	// format the message
    va_list args; // create variable list
    va_start( args, string);  // the name of the first variable is "Message"
    vsprintf( newstring, string, args); // Store the formatted string with vars in S 
    va_end( args); // end of argument list


    int len = strlen(newstring);
	int cntr;
    SIZE sz = {0,0};

    sz.cy = m_PixelHeight;      // set the height to the height of the bitmap

    // loop for the number of characters in string
	for(cntr = 0; cntr<len; cntr++)
	{
        //accumulate widths of characters to be drawn
        sz.cx += m_cWidths[newstring[cntr]];
	}

    return sz;
}
