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