📄 font.cpp
字号:
#include "Font.h"
#include "Context.h"
#include "dprintf.h"
#include <lang/Globals.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <config.h>
const int CHAR_X_SPACE = 0;
Font::Font() :
m_loaded( false )
{
}
Font::~Font()
{
m_img.destroy();
}
void Font::load( const char* fname, int w, int h )
{
// Source data pattern: 16 x 16 characters
dprintf( "Font::load: m_img.loadCustom( %s )\n", fname );
m_img.loadCustom( fname );
m_fontBaseWidth = w;
m_fontHeight = h;
process();
m_loaded = true;
}
void Font::process()
{
uint16_t* data = (uint16_t*) m_img.data();
uint16_t* markerLine = 0;
const int yBaseStep = ( m_img.pitch() >> 1 ) * m_fontHeight;
// get the marker color from the second pixel (the first pixel is the transparency color key)
uint16_t markerColor = data[1];
// Source data pattern: 16 x 16 characters
// Calculate character coordinates (x and y) and widths
// based on marker pixels in the surface
// while making marker pixels invisible
bool charProcessed = false;
bool widthCountingActive = false;
int charWidth = 0;
int xCoord = 0;
int yCoord = 0;
int yBase = 0;
int ch = 0;
for ( int y = 0; y < 16; y++ )
{
xCoord = 0;
for ( int x = 0; x < 16; x++ )
{
if ( ch == 0 )
{
//Empty character
m_charX[ch] = 0;
m_charY[ch] = 0;
m_charWidth[ch++] = 0;
xCoord += m_fontBaseWidth;
continue;
}
m_charX[ch] = xCoord; // store initial character x coordinate
m_charY[ch] = yCoord; // store character y coordinate
markerLine = &data[ yBase + xCoord ];
charProcessed = false;
widthCountingActive = false;
charWidth = 0;
// check character
for ( int i = 0; i < m_fontBaseWidth; i++ )
{
if ( markerLine[i] == markerColor )
{
// marker pixel
if ( !charProcessed && !widthCountingActive )
{
// start of marker pixel line
m_charX[ch] += i; // update x coordinate
widthCountingActive = true; // activate width counting
}
markerLine[i] &= 0x0FFF; // make the pixel invisible
}
else
{
// not marker pixel
if ( !charProcessed && widthCountingActive )
{
// end of marker pixel line
widthCountingActive = false; // inactivate width counting
charProcessed = true; // and mark the character processed
}
}
if ( widthCountingActive ) charWidth++; // update character width
}
m_charWidth[ch++] = charWidth; // store character width
xCoord += m_fontBaseWidth;
}
yBase += yBaseStep;
yCoord += m_fontHeight;
}
}
void Font::drawText( Context* context, int x, int y, int* outx, int* outy, const char* fmt, ... )
{
if ( !m_loaded ) return;
// format variable arguments
const unsigned MAX_MSG = 500;
char msg[MAX_MSG+4];
va_list marker;
va_start( marker, fmt );
vsprintf( msg, fmt, marker );
va_end( marker );
unsigned int len = strlen(msg);
assert( len < MAX_MSG ); // too long debug message
uint8_t* buffer = (uint8_t*)context->buffer();
int pitch = context->pitch();
int width = context->width();
int height = context->height();
Surface dst( buffer, pitch, width, height );
int rowx = x;
char ch = 0;
for ( int i = 0 ; i < (int)len ; ++i )
{
ch = msg[i];
if ( ch == 0 ) break;
if ( ch == '\n' )
{
x = rowx;
y += m_fontHeight;
continue;
}
int x0 = m_charX[ch];
int y0 = m_charY[ch];
int charWidth = m_charWidth[ch];
int x1 = x0 + charWidth;
if ( x1 > m_img.width() ) x1 = m_img.width();
Surface sf = m_img.clip( x0, y0, x1, y0 + m_fontHeight );
dst.blt( x, y, sf, Surface::BLEND_ALPHA1B );
x += charWidth + CHAR_X_SPACE;
}
y += m_fontHeight;
if ( outx )
*outx = x;
if ( outy )
*outy = y;
}
int Font::getTextWidth( const char* msg, int* outLines, int* outHeight ) const
{
if ( !m_loaded ) return 0;
int maxWidth = 0;
int lineWidth = 0;
int lines = 0;
char ch = 0;
for ( int i = 0; msg[i]; ++i )
{
ch = msg[i];
if ( ch != '\n' )
{
lineWidth += m_charWidth[ch] + CHAR_X_SPACE;
}
if ( ch == '\n' || msg[i + 1] == 0 )
{
if ( lineWidth > maxWidth ) maxWidth = lineWidth;
lineWidth = 0;
++lines;
}
}
if ( outLines ) *outLines = lines;
if ( outHeight ) *outHeight = lines * m_fontHeight;
return maxWidth;
}
int Font::fontHeight() const
{
if ( !m_loaded ) return 0;
return m_fontHeight;
}
// End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -