os/textandloc/fontservices/referencefonts/utils/bdfharn.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/textandloc/fontservices/referencefonts/utils/bdfharn.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,412 @@
     1.4 +/*
     1.5 +* Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +* Chris Cooper, 09 March 1999
    1.19 +* This application loads a scaleable open font and extracts a particular
    1.20 +* user-specified size from it which it then outputs as a BDF format font
    1.21 +* file. This can then be turned into an EPOC bitmap font using other tools.
    1.22 +* At the moment the required font name and PPEM size are specified in a
    1.23 +* program statement, so this utility must be recompiled. It is intended to
    1.24 +* change this to obtain the input from a text file - and to allow multiple
    1.25 +* conversions to be specified at once.
    1.26 +* This application has to be a Unicode build to function.
    1.27 +* If this #define is enabled than, instead of getting a useable BDF file,
    1.28 +* the hex char definitions are replaced by visible bitmaps of the chars.
    1.29 +* It should, therefore, be commented out in normal use.
    1.30 +*
    1.31 +*/
    1.32 +
    1.33 +//#define SHOW_FONT_PICTURES_INSTEAD_OF_HEX
    1.34 +
    1.35 +#include <e32std.h>
    1.36 +#include <e32test.h>
    1.37 +#include <bitstd.h>
    1.38 +#include <bitdev.h>
    1.39 +#include <fbs.h>
    1.40 +#include <f32file.h>
    1.41 +
    1.42 +
    1.43 +#include "bdfharn.h"
    1.44 +
    1.45 +TPtrC CBDFHarness::iFacename(_L("DejaVu Sans Condensed"));
    1.46 +TInt  CBDFHarness::iPixelSize = 8;
    1.47 +TPtrC CBDFHarness::iFilename(_L("Swi8br"));
    1.48 +TPtrC CBDFHarness::iUid(_L("268457817"));
    1.49 +
    1.50 +TFontPosture CBDFHarness::iPosture = EPostureUpright;
    1.51 +//TFontPosture CBDFHarness::iPosture = EPostureItalic;
    1.52 +
    1.53 +//TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightNormal;
    1.54 +TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightBold;
    1.55 +
    1.56 +TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosNormal;
    1.57 +//TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSuperscript;
    1.58 +//TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSubscript;
    1.59 +
    1.60 +TBuf<256> buffer;
    1.61 +
    1.62 +// this function is a hack to take a Unicode string containing
    1.63 +// only chars <= 255 and put out the 8 bit version to the file
    1.64 +void FileWrite8(RFile& aFile, const TDesC& aText)
    1.65 +	{
    1.66 +	// It's Unicode so we've got to step down from 16 bit desc to 8 bit file
    1.67 +	TInt length = aText.Length();
    1.68 +	HBufC8* buffer8 = HBufC8::NewMaxL(length);
    1.69 +	TPtr8 p = buffer8->Des();
    1.70 +	TUint16 c;
    1.71 +	TUint8 b;
    1.72 +
    1.73 +	int k = 0;
    1.74 +	for (int r = 0; r < length; r++)
    1.75 +		{
    1.76 +		c = aText[r];
    1.77 +		b = (TUint8)c;
    1.78 +		p[k++] = b;
    1.79 +		}
    1.80 +	aFile.Write(*buffer8);
    1.81 +	delete buffer8;
    1.82 +	}
    1.83 +
    1.84 +
    1.85 +CBDFHarness::CBDFHarness(const TDesC &aTitle, const TDesC &aHeading): iTest(aTitle)
    1.86 +	{
    1.87 +	iTest.Title();
    1.88 +	iTest.Start(aHeading);
    1.89 +	}
    1.90 +
    1.91 +
    1.92 +CBDFHarness* CBDFHarness::NewL(const TDesC &aTitle, const TDesC &aHeading)
    1.93 +	{
    1.94 +	CBDFHarness* t = new (ELeave)CBDFHarness(aTitle, aHeading);
    1.95 +	CleanupStack::PushL(t);
    1.96 +	t->ConstructL();
    1.97 +	CleanupStack::Pop();
    1.98 +	return t;
    1.99 +	}
   1.100 +
   1.101 +
   1.102 +void CBDFHarness::ConstructL()
   1.103 +	{
   1.104 +	User::LeaveIfError(RFbsSession::Connect());
   1.105 +	iFbs = RFbsSession::GetSession();
   1.106 +	if (iFbs == NULL)
   1.107 +		User::Leave(KErrGeneral);
   1.108 +	iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray4);
   1.109 +	iDev->ChangeScreenDevice(NULL);
   1.110 +	iDev->SetAutoUpdate(ETrue);
   1.111 +	iDev->CreateContext(iGc);
   1.112 +
   1.113 +	TFontSpec fs(iFacename, iPixelSize);
   1.114 +	fs.iFontStyle.SetPosture(iPosture);
   1.115 +	fs.iFontStyle.SetStrokeWeight(iStrokeWeight);
   1.116 +	fs.iFontStyle.SetPrintPosition(iPrintPosition);
   1.117 +	TInt error = iDev->GetNearestFontInPixels((CFont*&)iStandardFont,fs);
   1.118 +	if (error)
   1.119 +		User::Panic(_L("Could not create this font"),error);
   1.120 +	}
   1.121 +
   1.122 +
   1.123 +CBDFHarness::~CBDFHarness()
   1.124 +	{
   1.125 +	if (iStandardFont)
   1.126 +		iDev->ReleaseFont(iStandardFont);
   1.127 +	delete iGc;
   1.128 +	delete iDev;
   1.129 +	RFbsSession::Disconnect();
   1.130 +	iTest.Close();
   1.131 +	}
   1.132 +
   1.133 +
   1.134 +void CBDFHarness::MakeBDFFontL()
   1.135 +	{
   1.136 +	TOpenFontFaceAttrib attrib;
   1.137 +	iStandardFont->GetFaceAttrib(attrib);
   1.138 +	TPtrC familyName = attrib.FamilyName();
   1.139 +	TPtrC fullName = attrib.LocalFullName();
   1.140 +	TOpenFontMetrics fMetrics;
   1.141 +	iStandardFont->GetFontMetrics(fMetrics);
   1.142 +	iPPEM = fMetrics.Size();
   1.143 +
   1.144 +	// Open file session
   1.145 +	RFs file_session;
   1.146 +	User::LeaveIfError(file_session.Connect());
   1.147 +	file_session.MkDir(_L("\\BDFfonts\\"));
   1.148 +	// Open file
   1.149 +	RFile file;
   1.150 +	buffer.Format(_L("\\BDFfonts\\%S %d.bdf"), &fullName, iPPEM);
   1.151 +	file.Replace(file_session, buffer, EFileShareAny);
   1.152 +	// Extract global info
   1.153 +	// STARTFONT 2.2
   1.154 +	buffer.Format(_L("STARTFONT 2.2\r\n"));
   1.155 +	FileWrite8(file, buffer);
   1.156 +	// COMMENT <font name> [(Bold) ][(Italic) ]at <nn> pixels per em
   1.157 +	buffer.Format(_L("COMMENT %S "), &familyName);
   1.158 +	FileWrite8(file, buffer);
   1.159 +	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
   1.160 +		{
   1.161 +		buffer.Format(_L("(Bold) "));
   1.162 +		FileWrite8(file, buffer);
   1.163 +		}
   1.164 +	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
   1.165 +		{
   1.166 +		buffer.Format(_L("(Italic) "));
   1.167 +		FileWrite8(file, buffer);
   1.168 +		}
   1.169 +	buffer.Format(_L("at %d pixels per em\r\n"), iPPEM);
   1.170 +	FileWrite8(file, buffer);
   1.171 +	// COMMENT Generated by the EPOC BDF creator
   1.172 +	buffer.Format(_L("COMMENT Generated by the EPOC BDF creator\r\n"));
   1.173 +	FileWrite8(file, buffer);
   1.174 +	// FONT <font name>
   1.175 +	buffer.Format(_L("FONT %S\r\n"), &iFilename);
   1.176 +	FileWrite8(file, buffer);
   1.177 +	// SIZE <ppem> 72 72
   1.178 +	buffer.Format(_L("SIZE %d 72 72\r\n"), iPPEM);
   1.179 +	FileWrite8(file, buffer);
   1.180 +	// FONTBOUNDINGBOX <bbox pixel width> <bbox pixel height> <bbox x pixel offset> <bbox y pixel offset>
   1.181 +	TInt bbw = fMetrics.MaxWidth();
   1.182 +	TInt bbh = fMetrics.MaxHeight() + fMetrics.MaxDepth();
   1.183 +	TInt bbxo = 0;
   1.184 +	TInt bbyo = -1 * fMetrics.MaxDepth();
   1.185 +	buffer.Format(_L("FONTBOUNDINGBOX %d %d %d %d\r\n"), bbw, bbh, bbxo, bbyo);
   1.186 +	FileWrite8(file, buffer);
   1.187 +	// STARTPROPERTIES
   1.188 +	TInt numproperties = 5;
   1.189 +	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
   1.190 +		numproperties++;
   1.191 +	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
   1.192 +		numproperties++;
   1.193 +	buffer.Format(_L("STARTPROPERTIES %d\r\n"), numproperties);
   1.194 +	FileWrite8(file, buffer);
   1.195 +	buffer.Format(_L("Uid %S\r\n"), &iUid);
   1.196 +	FileWrite8(file, buffer);
   1.197 +	buffer.Format(_L("MaxNormalCharWidth "));
   1.198 +	FileWrite8(file, buffer);
   1.199 +	TInt maxWidth = bbw;
   1.200 +	buffer.Format(_L("%d\r\n"), maxWidth);
   1.201 +	FileWrite8(file, buffer);
   1.202 +	buffer.Format(_L("MaxConsecutiveFillChars 5\r\n"));
   1.203 +	FileWrite8(file, buffer);
   1.204 +	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
   1.205 +		{
   1.206 +		buffer.Format(_L("Bold 1\r\n"));
   1.207 +		FileWrite8(file, buffer);
   1.208 +		}
   1.209 +	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
   1.210 +		{
   1.211 +		buffer.Format(_L("Italic 1\r\n"));
   1.212 +		FileWrite8(file, buffer);
   1.213 +		}
   1.214 +	// FONT_ASCENT
   1.215 +	buffer.Format(_L("FONT_ASCENT %d\r\n"), fMetrics.Ascent());
   1.216 +	FileWrite8(file, buffer);
   1.217 +	// FONT_DESCENT
   1.218 +	buffer.Format(_L("FONT_DESCENT %d\r\n"), fMetrics.Descent());
   1.219 +	FileWrite8(file, buffer);
   1.220 +	// ENDPROPERTIES
   1.221 +	buffer.Format(_L("ENDPROPERTIES\r\n"));
   1.222 +	FileWrite8(file, buffer);
   1.223 +	// CHARS <number of glyphs>
   1.224 +	// Work out how many chars in font
   1.225 +	TInt charCount = 0;
   1.226 +	TInt i = 0;
   1.227 +	for ( i = 0; i <= 0xFFFF; i++ )
   1.228 +		{
   1.229 +		if ( iStandardFont->HasCharacter(i) )
   1.230 +			charCount++;
   1.231 +		}
   1.232 +	buffer.Format(_L("CHARS %d\r\n"), charCount);
   1.233 +	FileWrite8(file, buffer);
   1.234 +
   1.235 +	for ( i = 0; i <= 0xFFFF; i++ )
   1.236 +		{
   1.237 +		if ( iStandardFont->HasCharacter(i) )
   1.238 +			{
   1.239 +			// STARTCHAR <Unn in hex>
   1.240 +			buffer.Format(_L("STARTCHAR U%x\r\n"), i);
   1.241 +			FileWrite8(file, buffer);
   1.242 +			// ENCODING <usually nn decimal>
   1.243 +			buffer.Format(_L("ENCODING %d\r\n"), i);
   1.244 +			FileWrite8(file, buffer);
   1.245 +			// SWIDTH <swidth> 0
   1.246 +			// DWIDTH <swidth * (pointsize / 1000) * (device resolution / 72)> 0
   1.247 +			// DWIDTH <swidth * (ppem / 1000) * (72 / 72)> 0
   1.248 +			// but DWIDTH  = <advance in pixels> which we know
   1.249 +			// so SWIDTH = (DWIDTH * 1000) / ppem
   1.250 +			TOpenFontCharMetrics cMetrics;
   1.251 +			const TUint8* bitmapPtr;
   1.252 +			TSize dummy;
   1.253 +			iStandardFont->GetCharacterData(i, cMetrics, bitmapPtr, dummy);
   1.254 +			TInt dwidth = cMetrics.HorizAdvance();
   1.255 +			TReal dwidthReal = dwidth;
   1.256 +			TInt swidth = (TInt)(((dwidthReal * 1000) / iPPEM) + 0.5);
   1.257 +			buffer.Format(_L("SWIDTH %d 0\r\n"), swidth);
   1.258 +			FileWrite8(file, buffer);
   1.259 +			buffer.Format(_L("DWIDTH %d 0\r\n"), dwidth);
   1.260 +			FileWrite8(file, buffer);
   1.261 +			// BBX <bmap pixel width> <bmap pixel height> <bmap x pixel offset> <bmap y pixel offset>
   1.262 +			TInt bpw = cMetrics.Width();
   1.263 +			TInt bph = cMetrics.Height();
   1.264 +			TInt bxo = cMetrics.HorizBearingX();
   1.265 +			TInt byo = cMetrics.HorizBearingY() - bph; // Because openfont offsets are to top left and bdf is to bottom left
   1.266 +			buffer.Format(_L("BBX %d %d %d %d\r\n"), bpw, bph, bxo, byo);
   1.267 +			FileWrite8(file, buffer);
   1.268 +			// BITMAP
   1.269 +			buffer.Format(_L("BITMAP\r\n"));
   1.270 +			FileWrite8(file, buffer);
   1.271 +			TInt paddedWidth = ((bpw + 7) / 8);
   1.272 +			if (bph * paddedWidth)
   1.273 +				{
   1.274 +				TUint8* bitmap = new TUint8 [sizeof(TUint8) * bph * paddedWidth];
   1.275 +				DecodeBitmap(bpw, paddedWidth, bph, bitmapPtr, bitmap);
   1.276 +				for (TInt j = 0; j < bph; j++)
   1.277 +					{
   1.278 +					// Output one line of bitmap
   1.279 +#ifndef SHOW_FONT_PICTURES_INSTEAD_OF_HEX
   1.280 +					// This branch is the standard version that produces useable BDF files
   1.281 +					for (TInt k = paddedWidth - 1; k >= 0; k--)
   1.282 +						{
   1.283 +						TInt byte = *(bitmap + (j * paddedWidth) + k);
   1.284 +
   1.285 +						OutHex(byte / 16);
   1.286 +						FileWrite8(file, buffer);
   1.287 +						OutHex(byte % 16);
   1.288 +						FileWrite8(file, buffer);
   1.289 +						}
   1.290 +					buffer.Format(_L("\r\n"));
   1.291 +					FileWrite8(file, buffer);
   1.292 +#else
   1.293 +					// This branch shows the char bitmaps but does not produce useable BDF files
   1.294 +					buffer.Format(_L("["));
   1.295 +					FileWrite8(file, buffer);
   1.296 +					iBitNum = ((j + 1) * paddedWidth * 8) - 1;
   1.297 +					iBitMap = bitmap;
   1.298 +
   1.299 +					for (TInt k = 0; k < bpw; k++)
   1.300 +						{
   1.301 +						if (ReadBitBack())
   1.302 +							buffer.Format(_L("@"));
   1.303 +						else
   1.304 +							buffer.Format(_L(" "));
   1.305 +						FileWrite8(file, buffer);
   1.306 +						}
   1.307 +					for (k = bpw; k < 8 * paddedWidth; k++)
   1.308 +						{
   1.309 +						buffer.Format(_L("."));
   1.310 +						FileWrite8(file, buffer);
   1.311 +						}
   1.312 +					buffer.Format(_L("]\r\n"));
   1.313 +					FileWrite8(file, buffer);
   1.314 +#endif
   1.315 +					}
   1.316 +				delete [] bitmap;
   1.317 +				}
   1.318 +			// ENDCHAR
   1.319 +			buffer.Format(_L("ENDCHAR\r\n"));
   1.320 +			FileWrite8(file, buffer);
   1.321 +			}
   1.322 +		}
   1.323 +	// ENDFONT
   1.324 +	buffer.Format(_L("ENDFONT\r\n"));
   1.325 +	FileWrite8(file, buffer);
   1.326 +	// Close file
   1.327 +	file.Flush();
   1.328 +	file.Close();
   1.329 +	file_session.Close();
   1.330 +
   1.331 +	}
   1.332 +
   1.333 +TInt CBDFHarness::ReadBit()
   1.334 +	{
   1.335 +	TInt val = 1;
   1.336 +	for (TInt i = 0; i < (iBitNum % 8); i++)
   1.337 +		val *= 2;
   1.338 +	val = iBitMap[iBitNum / 8] & val;
   1.339 +	iBitNum++;
   1.340 +	return val ? 1 : 0;
   1.341 +	}
   1.342 +
   1.343 +TInt CBDFHarness::ReadBitBack()
   1.344 +	{
   1.345 +	TInt val = 1;
   1.346 +	for (TInt i = 0; i < (iBitNum % 8); i++)
   1.347 +		val *= 2;
   1.348 +	val = iBitMap[iBitNum / 8] & val;
   1.349 +	iBitNum--;
   1.350 +	return val ? 1 : 0;
   1.351 +	}
   1.352 +
   1.353 +void CBDFHarness::OutHex(TInt aOneHexDigit)
   1.354 +	{
   1.355 +	if (aOneHexDigit <= 9)
   1.356 +		buffer.Format(_L("%c"), '0' + aOneHexDigit);
   1.357 +	else
   1.358 +		buffer.Format(_L("%c"), 'a' + aOneHexDigit - 10);
   1.359 +	}
   1.360 +
   1.361 +void CBDFHarness::DecodeBitmap(TInt aWidth, TInt aPaddedWidth, TInt aHeight, const TUint8* aCodedBitmap, TUint8* aBitMap)
   1.362 +	{
   1.363 +	// Zero the bitmap
   1.364 +	for (TInt i = 0; i < aPaddedWidth * aHeight; i++)
   1.365 +		aBitMap[i] = 0;
   1.366 +	TInt repeats = 0;
   1.367 +	iBitNum = 0;
   1.368 +	iBitMap = aCodedBitmap;
   1.369 +	for (TInt linesRead = 0; linesRead < aHeight; linesRead += repeats)
   1.370 +		{
   1.371 +		TInt repeating = !(ReadBit());
   1.372 +		
   1.373 +		// Intended behavior is for the line of code below to be evaluated left to right.
   1.374 +		//    repeats = (1 * ReadBit()) + (2 * ReadBit()) + (4 * ReadBit()) + (8 * ReadBit());
   1.375 +		// However, the order in which calls to ReadBit() above are evaluated is undefined,
   1.376 +		// and is compiler dependent.
   1.377 +		// The following code ensures that the correct code is used:
   1.378 +		TInt bit1 = ReadBit();
   1.379 +		TInt bit2 = ReadBit();
   1.380 +		TInt bit3 = ReadBit();
   1.381 +		TInt bit4 = ReadBit();
   1.382 +		repeats = (1 * bit1) + (2 * bit2) + (4 * bit3) + (8 * bit4);
   1.383 +
   1.384 +		TInt padVal = (aPaddedWidth * 8) - aWidth;
   1.385 +		if (repeating)
   1.386 +			{
   1.387 +			for (TInt j = padVal + aWidth - 1; j >= padVal; j--)
   1.388 +				{
   1.389 +				TInt value = ReadBit();
   1.390 +				for (TInt k = 0; k < (j % 8); k++)
   1.391 +					value *= 2;
   1.392 +				for (TInt l = 0; l < repeats; l++)
   1.393 +					{
   1.394 +					aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] =
   1.395 +						TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value);
   1.396 +					}
   1.397 +				}
   1.398 +			}
   1.399 +		else
   1.400 +			{
   1.401 +			for (TInt l = 0; l < repeats; l++)
   1.402 +				{
   1.403 +				for (TInt j = padVal + aWidth - 1; j >= padVal; j--)
   1.404 +					{
   1.405 +					TInt value = ReadBit();
   1.406 +					for (TInt k = 0; k < (j % 8); k++)
   1.407 +						value *= 2;
   1.408 +					aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] =
   1.409 +						TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value);
   1.410 +					}
   1.411 +				}
   1.412 +			}
   1.413 +		}
   1.414 +	}
   1.415 +