sl@0: /* sl@0: * Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Chris Cooper, 09 March 1999 sl@0: * This application loads a scaleable open font and extracts a particular sl@0: * user-specified size from it which it then outputs as a BDF format font sl@0: * file. This can then be turned into an EPOC bitmap font using other tools. sl@0: * At the moment the required font name and PPEM size are specified in a sl@0: * program statement, so this utility must be recompiled. It is intended to sl@0: * change this to obtain the input from a text file - and to allow multiple sl@0: * conversions to be specified at once. sl@0: * This application has to be a Unicode build to function. sl@0: * If this #define is enabled than, instead of getting a useable BDF file, sl@0: * the hex char definitions are replaced by visible bitmaps of the chars. sl@0: * It should, therefore, be commented out in normal use. sl@0: * sl@0: */ sl@0: sl@0: //#define SHOW_FONT_PICTURES_INSTEAD_OF_HEX sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: #include "bdfharn.h" sl@0: sl@0: TPtrC CBDFHarness::iFacename(_L("DejaVu Sans Condensed")); sl@0: TInt CBDFHarness::iPixelSize = 8; sl@0: TPtrC CBDFHarness::iFilename(_L("Swi8br")); sl@0: TPtrC CBDFHarness::iUid(_L("268457817")); sl@0: sl@0: TFontPosture CBDFHarness::iPosture = EPostureUpright; sl@0: //TFontPosture CBDFHarness::iPosture = EPostureItalic; sl@0: sl@0: //TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightNormal; sl@0: TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightBold; sl@0: sl@0: TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosNormal; sl@0: //TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSuperscript; sl@0: //TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSubscript; sl@0: sl@0: TBuf<256> buffer; sl@0: sl@0: // this function is a hack to take a Unicode string containing sl@0: // only chars <= 255 and put out the 8 bit version to the file sl@0: void FileWrite8(RFile& aFile, const TDesC& aText) sl@0: { sl@0: // It's Unicode so we've got to step down from 16 bit desc to 8 bit file sl@0: TInt length = aText.Length(); sl@0: HBufC8* buffer8 = HBufC8::NewMaxL(length); sl@0: TPtr8 p = buffer8->Des(); sl@0: TUint16 c; sl@0: TUint8 b; sl@0: sl@0: int k = 0; sl@0: for (int r = 0; r < length; r++) sl@0: { sl@0: c = aText[r]; sl@0: b = (TUint8)c; sl@0: p[k++] = b; sl@0: } sl@0: aFile.Write(*buffer8); sl@0: delete buffer8; sl@0: } sl@0: sl@0: sl@0: CBDFHarness::CBDFHarness(const TDesC &aTitle, const TDesC &aHeading): iTest(aTitle) sl@0: { sl@0: iTest.Title(); sl@0: iTest.Start(aHeading); sl@0: } sl@0: sl@0: sl@0: CBDFHarness* CBDFHarness::NewL(const TDesC &aTitle, const TDesC &aHeading) sl@0: { sl@0: CBDFHarness* t = new (ELeave)CBDFHarness(aTitle, aHeading); sl@0: CleanupStack::PushL(t); sl@0: t->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return t; sl@0: } sl@0: sl@0: sl@0: void CBDFHarness::ConstructL() sl@0: { sl@0: User::LeaveIfError(RFbsSession::Connect()); sl@0: iFbs = RFbsSession::GetSession(); sl@0: if (iFbs == NULL) sl@0: User::Leave(KErrGeneral); sl@0: iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray4); sl@0: iDev->ChangeScreenDevice(NULL); sl@0: iDev->SetAutoUpdate(ETrue); sl@0: iDev->CreateContext(iGc); sl@0: sl@0: TFontSpec fs(iFacename, iPixelSize); sl@0: fs.iFontStyle.SetPosture(iPosture); sl@0: fs.iFontStyle.SetStrokeWeight(iStrokeWeight); sl@0: fs.iFontStyle.SetPrintPosition(iPrintPosition); sl@0: TInt error = iDev->GetNearestFontInPixels((CFont*&)iStandardFont,fs); sl@0: if (error) sl@0: User::Panic(_L("Could not create this font"),error); sl@0: } sl@0: sl@0: sl@0: CBDFHarness::~CBDFHarness() sl@0: { sl@0: if (iStandardFont) sl@0: iDev->ReleaseFont(iStandardFont); sl@0: delete iGc; sl@0: delete iDev; sl@0: RFbsSession::Disconnect(); sl@0: iTest.Close(); sl@0: } sl@0: sl@0: sl@0: void CBDFHarness::MakeBDFFontL() sl@0: { sl@0: TOpenFontFaceAttrib attrib; sl@0: iStandardFont->GetFaceAttrib(attrib); sl@0: TPtrC familyName = attrib.FamilyName(); sl@0: TPtrC fullName = attrib.LocalFullName(); sl@0: TOpenFontMetrics fMetrics; sl@0: iStandardFont->GetFontMetrics(fMetrics); sl@0: iPPEM = fMetrics.Size(); sl@0: sl@0: // Open file session sl@0: RFs file_session; sl@0: User::LeaveIfError(file_session.Connect()); sl@0: file_session.MkDir(_L("\\BDFfonts\\")); sl@0: // Open file sl@0: RFile file; sl@0: buffer.Format(_L("\\BDFfonts\\%S %d.bdf"), &fullName, iPPEM); sl@0: file.Replace(file_session, buffer, EFileShareAny); sl@0: // Extract global info sl@0: // STARTFONT 2.2 sl@0: buffer.Format(_L("STARTFONT 2.2\r\n")); sl@0: FileWrite8(file, buffer); sl@0: // COMMENT [(Bold) ][(Italic) ]at pixels per em sl@0: buffer.Format(_L("COMMENT %S "), &familyName); sl@0: FileWrite8(file, buffer); sl@0: if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold) sl@0: { sl@0: buffer.Format(_L("(Bold) ")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic) sl@0: { sl@0: buffer.Format(_L("(Italic) ")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: buffer.Format(_L("at %d pixels per em\r\n"), iPPEM); sl@0: FileWrite8(file, buffer); sl@0: // COMMENT Generated by the EPOC BDF creator sl@0: buffer.Format(_L("COMMENT Generated by the EPOC BDF creator\r\n")); sl@0: FileWrite8(file, buffer); sl@0: // FONT sl@0: buffer.Format(_L("FONT %S\r\n"), &iFilename); sl@0: FileWrite8(file, buffer); sl@0: // SIZE 72 72 sl@0: buffer.Format(_L("SIZE %d 72 72\r\n"), iPPEM); sl@0: FileWrite8(file, buffer); sl@0: // FONTBOUNDINGBOX sl@0: TInt bbw = fMetrics.MaxWidth(); sl@0: TInt bbh = fMetrics.MaxHeight() + fMetrics.MaxDepth(); sl@0: TInt bbxo = 0; sl@0: TInt bbyo = -1 * fMetrics.MaxDepth(); sl@0: buffer.Format(_L("FONTBOUNDINGBOX %d %d %d %d\r\n"), bbw, bbh, bbxo, bbyo); sl@0: FileWrite8(file, buffer); sl@0: // STARTPROPERTIES sl@0: TInt numproperties = 5; sl@0: if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold) sl@0: numproperties++; sl@0: if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic) sl@0: numproperties++; sl@0: buffer.Format(_L("STARTPROPERTIES %d\r\n"), numproperties); sl@0: FileWrite8(file, buffer); sl@0: buffer.Format(_L("Uid %S\r\n"), &iUid); sl@0: FileWrite8(file, buffer); sl@0: buffer.Format(_L("MaxNormalCharWidth ")); sl@0: FileWrite8(file, buffer); sl@0: TInt maxWidth = bbw; sl@0: buffer.Format(_L("%d\r\n"), maxWidth); sl@0: FileWrite8(file, buffer); sl@0: buffer.Format(_L("MaxConsecutiveFillChars 5\r\n")); sl@0: FileWrite8(file, buffer); sl@0: if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold) sl@0: { sl@0: buffer.Format(_L("Bold 1\r\n")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic) sl@0: { sl@0: buffer.Format(_L("Italic 1\r\n")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: // FONT_ASCENT sl@0: buffer.Format(_L("FONT_ASCENT %d\r\n"), fMetrics.Ascent()); sl@0: FileWrite8(file, buffer); sl@0: // FONT_DESCENT sl@0: buffer.Format(_L("FONT_DESCENT %d\r\n"), fMetrics.Descent()); sl@0: FileWrite8(file, buffer); sl@0: // ENDPROPERTIES sl@0: buffer.Format(_L("ENDPROPERTIES\r\n")); sl@0: FileWrite8(file, buffer); sl@0: // CHARS sl@0: // Work out how many chars in font sl@0: TInt charCount = 0; sl@0: TInt i = 0; sl@0: for ( i = 0; i <= 0xFFFF; i++ ) sl@0: { sl@0: if ( iStandardFont->HasCharacter(i) ) sl@0: charCount++; sl@0: } sl@0: buffer.Format(_L("CHARS %d\r\n"), charCount); sl@0: FileWrite8(file, buffer); sl@0: sl@0: for ( i = 0; i <= 0xFFFF; i++ ) sl@0: { sl@0: if ( iStandardFont->HasCharacter(i) ) sl@0: { sl@0: // STARTCHAR sl@0: buffer.Format(_L("STARTCHAR U%x\r\n"), i); sl@0: FileWrite8(file, buffer); sl@0: // ENCODING sl@0: buffer.Format(_L("ENCODING %d\r\n"), i); sl@0: FileWrite8(file, buffer); sl@0: // SWIDTH 0 sl@0: // DWIDTH 0 sl@0: // DWIDTH 0 sl@0: // but DWIDTH = which we know sl@0: // so SWIDTH = (DWIDTH * 1000) / ppem sl@0: TOpenFontCharMetrics cMetrics; sl@0: const TUint8* bitmapPtr; sl@0: TSize dummy; sl@0: iStandardFont->GetCharacterData(i, cMetrics, bitmapPtr, dummy); sl@0: TInt dwidth = cMetrics.HorizAdvance(); sl@0: TReal dwidthReal = dwidth; sl@0: TInt swidth = (TInt)(((dwidthReal * 1000) / iPPEM) + 0.5); sl@0: buffer.Format(_L("SWIDTH %d 0\r\n"), swidth); sl@0: FileWrite8(file, buffer); sl@0: buffer.Format(_L("DWIDTH %d 0\r\n"), dwidth); sl@0: FileWrite8(file, buffer); sl@0: // BBX sl@0: TInt bpw = cMetrics.Width(); sl@0: TInt bph = cMetrics.Height(); sl@0: TInt bxo = cMetrics.HorizBearingX(); sl@0: TInt byo = cMetrics.HorizBearingY() - bph; // Because openfont offsets are to top left and bdf is to bottom left sl@0: buffer.Format(_L("BBX %d %d %d %d\r\n"), bpw, bph, bxo, byo); sl@0: FileWrite8(file, buffer); sl@0: // BITMAP sl@0: buffer.Format(_L("BITMAP\r\n")); sl@0: FileWrite8(file, buffer); sl@0: TInt paddedWidth = ((bpw + 7) / 8); sl@0: if (bph * paddedWidth) sl@0: { sl@0: TUint8* bitmap = new TUint8 [sizeof(TUint8) * bph * paddedWidth]; sl@0: DecodeBitmap(bpw, paddedWidth, bph, bitmapPtr, bitmap); sl@0: for (TInt j = 0; j < bph; j++) sl@0: { sl@0: // Output one line of bitmap sl@0: #ifndef SHOW_FONT_PICTURES_INSTEAD_OF_HEX sl@0: // This branch is the standard version that produces useable BDF files sl@0: for (TInt k = paddedWidth - 1; k >= 0; k--) sl@0: { sl@0: TInt byte = *(bitmap + (j * paddedWidth) + k); sl@0: sl@0: OutHex(byte / 16); sl@0: FileWrite8(file, buffer); sl@0: OutHex(byte % 16); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: buffer.Format(_L("\r\n")); sl@0: FileWrite8(file, buffer); sl@0: #else sl@0: // This branch shows the char bitmaps but does not produce useable BDF files sl@0: buffer.Format(_L("[")); sl@0: FileWrite8(file, buffer); sl@0: iBitNum = ((j + 1) * paddedWidth * 8) - 1; sl@0: iBitMap = bitmap; sl@0: sl@0: for (TInt k = 0; k < bpw; k++) sl@0: { sl@0: if (ReadBitBack()) sl@0: buffer.Format(_L("@")); sl@0: else sl@0: buffer.Format(_L(" ")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: for (k = bpw; k < 8 * paddedWidth; k++) sl@0: { sl@0: buffer.Format(_L(".")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: buffer.Format(_L("]\r\n")); sl@0: FileWrite8(file, buffer); sl@0: #endif sl@0: } sl@0: delete [] bitmap; sl@0: } sl@0: // ENDCHAR sl@0: buffer.Format(_L("ENDCHAR\r\n")); sl@0: FileWrite8(file, buffer); sl@0: } sl@0: } sl@0: // ENDFONT sl@0: buffer.Format(_L("ENDFONT\r\n")); sl@0: FileWrite8(file, buffer); sl@0: // Close file sl@0: file.Flush(); sl@0: file.Close(); sl@0: file_session.Close(); sl@0: sl@0: } sl@0: sl@0: TInt CBDFHarness::ReadBit() sl@0: { sl@0: TInt val = 1; sl@0: for (TInt i = 0; i < (iBitNum % 8); i++) sl@0: val *= 2; sl@0: val = iBitMap[iBitNum / 8] & val; sl@0: iBitNum++; sl@0: return val ? 1 : 0; sl@0: } sl@0: sl@0: TInt CBDFHarness::ReadBitBack() sl@0: { sl@0: TInt val = 1; sl@0: for (TInt i = 0; i < (iBitNum % 8); i++) sl@0: val *= 2; sl@0: val = iBitMap[iBitNum / 8] & val; sl@0: iBitNum--; sl@0: return val ? 1 : 0; sl@0: } sl@0: sl@0: void CBDFHarness::OutHex(TInt aOneHexDigit) sl@0: { sl@0: if (aOneHexDigit <= 9) sl@0: buffer.Format(_L("%c"), '0' + aOneHexDigit); sl@0: else sl@0: buffer.Format(_L("%c"), 'a' + aOneHexDigit - 10); sl@0: } sl@0: sl@0: void CBDFHarness::DecodeBitmap(TInt aWidth, TInt aPaddedWidth, TInt aHeight, const TUint8* aCodedBitmap, TUint8* aBitMap) sl@0: { sl@0: // Zero the bitmap sl@0: for (TInt i = 0; i < aPaddedWidth * aHeight; i++) sl@0: aBitMap[i] = 0; sl@0: TInt repeats = 0; sl@0: iBitNum = 0; sl@0: iBitMap = aCodedBitmap; sl@0: for (TInt linesRead = 0; linesRead < aHeight; linesRead += repeats) sl@0: { sl@0: TInt repeating = !(ReadBit()); sl@0: sl@0: // Intended behavior is for the line of code below to be evaluated left to right. sl@0: // repeats = (1 * ReadBit()) + (2 * ReadBit()) + (4 * ReadBit()) + (8 * ReadBit()); sl@0: // However, the order in which calls to ReadBit() above are evaluated is undefined, sl@0: // and is compiler dependent. sl@0: // The following code ensures that the correct code is used: sl@0: TInt bit1 = ReadBit(); sl@0: TInt bit2 = ReadBit(); sl@0: TInt bit3 = ReadBit(); sl@0: TInt bit4 = ReadBit(); sl@0: repeats = (1 * bit1) + (2 * bit2) + (4 * bit3) + (8 * bit4); sl@0: sl@0: TInt padVal = (aPaddedWidth * 8) - aWidth; sl@0: if (repeating) sl@0: { sl@0: for (TInt j = padVal + aWidth - 1; j >= padVal; j--) sl@0: { sl@0: TInt value = ReadBit(); sl@0: for (TInt k = 0; k < (j % 8); k++) sl@0: value *= 2; sl@0: for (TInt l = 0; l < repeats; l++) sl@0: { sl@0: aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] = sl@0: TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (TInt l = 0; l < repeats; l++) sl@0: { sl@0: for (TInt j = padVal + aWidth - 1; j >= padVal; j--) sl@0: { sl@0: TInt value = ReadBit(); sl@0: for (TInt k = 0; k < (j % 8); k++) sl@0: value *= 2; sl@0: aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] = sl@0: TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: