📄 s2font.cpp
字号:
/* s2font.cpp
*
* Text rendering class for s2font bitmap fonts
*
* Copyright 2004 Petteri Kangaslampi
*
* See license.txt for full copyright and license information.
*/
#include <fbs.h>
#include <f32file.h>
#include <coemain.h>
#include "s2font.h"
_LIT(KPanic, "S2Font");
const TInt KPanicUnsupportedBitmapFormat = 1;
const TInt KPanicOutOfBitmapBounds = 2;
const TUint32 KS2FontMagic = 0x53324f4e; // S2FN
const TUint32 KFormatVersion = 0x00010000;
// Read an 8-bit unsigned integer from font data file
static inline TUint8 ReadU8(TUint8 *aData) {
return *aData;
}
// Read a 16-bit unsigned integer from font data file
static inline TUint16 ReadU16(TUint8 *aData) {
return (TUint16) ((((TUint16)aData[0]) << 8) | ((TUint16) aData[1]));
}
// Read a 32-bit unsigned integer from font data file
static inline TUint32 ReadU32(TUint8 *aData) {
return ((((TUint32)aData[0]) << 24) |
(((TUint32)aData[1]) << 16) |
(((TUint32)aData[2]) << 8) |
((TUint32)aData[3]));
}
// Factory
CS2Font *CS2Font::NewL(const TDesC &aFileName) {
CS2Font *self = new (ELeave) CS2Font();
CleanupStack::PushL(self);
self->ConstructL(aFileName);
CleanupStack::Pop();
return self;
}
// Constructor
CS2Font::CS2Font() {
Mem::FillZ(iFontPtr, 256 * sizeof(TUint32*));
}
// Destructor
CS2Font::~CS2Font() {
TInt i;
for ( i = 0; i < 256; i++ ) {
delete [] iFontPtr[i];
}
delete [] iFontData;
delete [] iUnknownCharData;
}
// Constructor
void CS2Font::ConstructL(const TDesC &aFileName) {
// Read the font file into memory
RFile file;
User::LeaveIfError(file.Open(CCoeEnv::Static()->FsSession(),
aFileName,
EFileRead | EFileShareReadersOnly));
CleanupClosePushL(file);
TInt fileSize;
User::LeaveIfError(file.Size(fileSize));
iFontData = new (ELeave) TUint8[fileSize];
TPtr8 fontPtr(iFontData, fileSize);
User::LeaveIfError(file.Read(fontPtr));
if ( fontPtr.Size() != fileSize ) {
User::Leave(KErrGeneral);
}
CleanupStack::PopAndDestroy(); // file
// Parse the file header
TUint8 *p = iFontData;
if ( fileSize < 24 ) {
User::Leave(KErrCorrupt);
}
if ( ReadU32(p) != KS2FontMagic ) {
User::Leave(KErrCorrupt);
}
p += 4;
if ( ReadU32(p) != KFormatVersion ) {
User::Leave(KErrNotSupported);
}
p += 4;
iNumChars = (TInt) ReadU32(p);
if ( iNumChars > 65536 ) {
User::Leave(KErrCorrupt);
}
p += 4;
iCharWidth = (TInt) ReadU32(p);
iCharHeight = (TInt) ReadU32(p+4);
iByteWidth = (iCharWidth+7) / 8;
if ( (iCharWidth < 0) || (iCharHeight < 0) ) {
User::Leave(KErrCorrupt);
}
p += 8;
// Skip the encoding for now
while ( (*p != 0) && ((p-iFontData) < fileSize) ) {
p++;
}
p++;
if ( p >= (iFontData+fileSize) ) {
User::Leave(KErrCorrupt);
}
// Check that the length is right
if ( (p + iNumChars*(2+iByteWidth*iCharHeight)) !=
(iFontData + fileSize) ) {
User::Leave(KErrCorrupt);
}
// Build pointers to the real character data
TInt n = iNumChars;
while ( n-- ) {
TUint c = ReadU16(p);
p += 2;
TUint hi = c >> 8;
TUint lo = c & 0xff;
if ( hi > 256 ) {
User::Leave(KErrCorrupt);
}
if ( iFontPtr[hi] == NULL ) {
iFontPtr[hi] = new (ELeave) TUint8*[256];
Mem::FillZ(iFontPtr[hi], 256*sizeof(TUint8*));
}
iFontPtr[hi][lo] = p;
p += iByteWidth * iCharHeight;
}
// Build blank data for unknown characters
iUnknownCharData = new (ELeave) TUint8[iCharHeight*iByteWidth];
Mem::FillZ(iUnknownCharData, iCharHeight*iByteWidth);
}
// Font size in pixels
TSize CS2Font::FontSize() const {
return TSize(iCharWidth, iCharHeight);
}
// Render text
void CS2Font::RenderText(CFbsBitmap &aBitmap, const TDesC &aText,
TInt aXOffset, TInt aYOffset, TRgb aFgColor,
TRgb aBgColor) const {
switch ( aBitmap.DisplayMode() ) {
case EColor4K: {
TBitmapUtil util(&aBitmap);
util.Begin(TPoint(0,0));
RenderTextLockedColor4K(aBitmap, aText, aXOffset, aYOffset,
aFgColor, aBgColor);
util.End();
break;
}
case EColor64K: {
TBitmapUtil util(&aBitmap);
util.Begin(TPoint(0,0));
RenderTextLockedColor64K(aBitmap, aText, aXOffset, aYOffset,
aFgColor, aBgColor);
util.End();
break;
}
default:
User::Panic(KPanic, KPanicUnsupportedBitmapFormat);
}
}
// Render text to a locked EColor4K bitmap
void CS2Font::RenderTextLockedColor4K(CFbsBitmap &aBitmap, const TDesC &aText,
TInt aXOffset, TInt aYOffset,
TRgb aFgColor, TRgb aBgColor) const {
RenderTextLocked16bpp(aBitmap, aText, aXOffset, aYOffset,
(TUint16)aFgColor.Color4K(),
(TUint16)aBgColor.Color4K());
}
// Render text to a locked EColor64K bitmap
void CS2Font::RenderTextLockedColor64K(CFbsBitmap &aBitmap, const TDesC &aText,
TInt aXOffset, TInt aYOffset,
TRgb aFgColor, TRgb aBgColor) const {
RenderTextLocked16bpp(aBitmap, aText, aXOffset, aYOffset,
(TUint16)aFgColor.Color64K(),
(TUint16)aBgColor.Color64K());
}
// Render text to a locked 16-bpp bitmap
void CS2Font::RenderTextLocked16bpp(CFbsBitmap &aBitmap, const TDesC &aText,
TInt aXOffset, TInt aYOffset,
TUint16 aFgData, TUint16 aBgData) const {
// Check that the text fits inside the bitmap
TInt textLen = aText.Length();
TSize size = aBitmap.SizeInPixels();
if ( (aXOffset < 0) || (aYOffset < 0) ||
((aXOffset + textLen*iCharWidth) > size.iWidth) ||
((aYOffset + iCharHeight) > size.iHeight) ) {
User::Panic(KPanic, KPanicOutOfBitmapBounds);
}
// Build pointers
TUint8 *data = (TUint8*) aBitmap.DataAddress();
TInt lineLen = CFbsBitmap::ScanLineLength(aBitmap.SizeInPixels().iWidth,
EColor4K);
TUint8 *dest = data + aYOffset*lineLen + aXOffset*2;
// Create color bitmap data
TUint8 fg0 = (TUint8) (aFgData & 0xff);
TUint8 fg1 = (TUint8) ((aFgData >> 8) & 0xff);
TUint8 bg0 = (TUint8) (aBgData & 0xff);
TUint8 bg1 = (TUint8) ((aBgData >> 8) & 0xff);
// Render the text
for ( TInt i = 0; i < textLen; i++ ) {
// Find font data for this character
TUint c = aText[i];
TUint hi = c >> 8;
TUint lo = c & 0xff;
TUint8 *s;
if ( (c > 65536) || (iFontPtr[hi] == NULL) ||
(iFontPtr[hi][lo] == NULL) ) {
// Unknown character, just fill with background color
s = iUnknownCharData;
} else {
// Valid character
s = iFontPtr[hi][lo];
}
// Draw all lines
TUint8 *dl = dest;
TInt rows = iCharHeight;
while ( rows-- ) {
// Draw all bytes on the line
TUint8 *d = dl;
TInt cols = iCharWidth;
TInt bytes = iByteWidth;
while ( bytes-- ) {
TUint b = *s++;
TInt now = cols;
if ( now > 8 ) {
now = 8;
}
cols -= now;
// Draw all pixels from this byte
while ( now-- ) {
if ( b & 0x80 ) {
d[0] = fg0;
d[1] = fg1;
} else {
d[0] = bg0;
d[1] = bg1;
}
d += 2;
b = b << 1;
}
}
dl += lineLen;
}
dest += iCharWidth*2;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -