os/textandloc/fontservices/referencefonts/utils/bdfharn.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
* Chris Cooper, 09 March 1999
sl@0
    16
* This application loads a scaleable open font and extracts a particular
sl@0
    17
* user-specified size from it which it then outputs as a BDF format font
sl@0
    18
* file. This can then be turned into an EPOC bitmap font using other tools.
sl@0
    19
* At the moment the required font name and PPEM size are specified in a
sl@0
    20
* program statement, so this utility must be recompiled. It is intended to
sl@0
    21
* change this to obtain the input from a text file - and to allow multiple
sl@0
    22
* conversions to be specified at once.
sl@0
    23
* This application has to be a Unicode build to function.
sl@0
    24
* If this #define is enabled than, instead of getting a useable BDF file,
sl@0
    25
* the hex char definitions are replaced by visible bitmaps of the chars.
sl@0
    26
* It should, therefore, be commented out in normal use.
sl@0
    27
*
sl@0
    28
*/
sl@0
    29
sl@0
    30
//#define SHOW_FONT_PICTURES_INSTEAD_OF_HEX
sl@0
    31
sl@0
    32
#include <e32std.h>
sl@0
    33
#include <e32test.h>
sl@0
    34
#include <bitstd.h>
sl@0
    35
#include <bitdev.h>
sl@0
    36
#include <fbs.h>
sl@0
    37
#include <f32file.h>
sl@0
    38
sl@0
    39
sl@0
    40
#include "bdfharn.h"
sl@0
    41
sl@0
    42
TPtrC CBDFHarness::iFacename(_L("DejaVu Sans Condensed"));
sl@0
    43
TInt  CBDFHarness::iPixelSize = 8;
sl@0
    44
TPtrC CBDFHarness::iFilename(_L("Swi8br"));
sl@0
    45
TPtrC CBDFHarness::iUid(_L("268457817"));
sl@0
    46
sl@0
    47
TFontPosture CBDFHarness::iPosture = EPostureUpright;
sl@0
    48
//TFontPosture CBDFHarness::iPosture = EPostureItalic;
sl@0
    49
sl@0
    50
//TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightNormal;
sl@0
    51
TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightBold;
sl@0
    52
sl@0
    53
TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosNormal;
sl@0
    54
//TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSuperscript;
sl@0
    55
//TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSubscript;
sl@0
    56
sl@0
    57
TBuf<256> buffer;
sl@0
    58
sl@0
    59
// this function is a hack to take a Unicode string containing
sl@0
    60
// only chars <= 255 and put out the 8 bit version to the file
sl@0
    61
void FileWrite8(RFile& aFile, const TDesC& aText)
sl@0
    62
	{
sl@0
    63
	// It's Unicode so we've got to step down from 16 bit desc to 8 bit file
sl@0
    64
	TInt length = aText.Length();
sl@0
    65
	HBufC8* buffer8 = HBufC8::NewMaxL(length);
sl@0
    66
	TPtr8 p = buffer8->Des();
sl@0
    67
	TUint16 c;
sl@0
    68
	TUint8 b;
sl@0
    69
sl@0
    70
	int k = 0;
sl@0
    71
	for (int r = 0; r < length; r++)
sl@0
    72
		{
sl@0
    73
		c = aText[r];
sl@0
    74
		b = (TUint8)c;
sl@0
    75
		p[k++] = b;
sl@0
    76
		}
sl@0
    77
	aFile.Write(*buffer8);
sl@0
    78
	delete buffer8;
sl@0
    79
	}
sl@0
    80
sl@0
    81
sl@0
    82
CBDFHarness::CBDFHarness(const TDesC &aTitle, const TDesC &aHeading): iTest(aTitle)
sl@0
    83
	{
sl@0
    84
	iTest.Title();
sl@0
    85
	iTest.Start(aHeading);
sl@0
    86
	}
sl@0
    87
sl@0
    88
sl@0
    89
CBDFHarness* CBDFHarness::NewL(const TDesC &aTitle, const TDesC &aHeading)
sl@0
    90
	{
sl@0
    91
	CBDFHarness* t = new (ELeave)CBDFHarness(aTitle, aHeading);
sl@0
    92
	CleanupStack::PushL(t);
sl@0
    93
	t->ConstructL();
sl@0
    94
	CleanupStack::Pop();
sl@0
    95
	return t;
sl@0
    96
	}
sl@0
    97
sl@0
    98
sl@0
    99
void CBDFHarness::ConstructL()
sl@0
   100
	{
sl@0
   101
	User::LeaveIfError(RFbsSession::Connect());
sl@0
   102
	iFbs = RFbsSession::GetSession();
sl@0
   103
	if (iFbs == NULL)
sl@0
   104
		User::Leave(KErrGeneral);
sl@0
   105
	iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray4);
sl@0
   106
	iDev->ChangeScreenDevice(NULL);
sl@0
   107
	iDev->SetAutoUpdate(ETrue);
sl@0
   108
	iDev->CreateContext(iGc);
sl@0
   109
sl@0
   110
	TFontSpec fs(iFacename, iPixelSize);
sl@0
   111
	fs.iFontStyle.SetPosture(iPosture);
sl@0
   112
	fs.iFontStyle.SetStrokeWeight(iStrokeWeight);
sl@0
   113
	fs.iFontStyle.SetPrintPosition(iPrintPosition);
sl@0
   114
	TInt error = iDev->GetNearestFontInPixels((CFont*&)iStandardFont,fs);
sl@0
   115
	if (error)
sl@0
   116
		User::Panic(_L("Could not create this font"),error);
sl@0
   117
	}
sl@0
   118
sl@0
   119
sl@0
   120
CBDFHarness::~CBDFHarness()
sl@0
   121
	{
sl@0
   122
	if (iStandardFont)
sl@0
   123
		iDev->ReleaseFont(iStandardFont);
sl@0
   124
	delete iGc;
sl@0
   125
	delete iDev;
sl@0
   126
	RFbsSession::Disconnect();
sl@0
   127
	iTest.Close();
sl@0
   128
	}
sl@0
   129
sl@0
   130
sl@0
   131
void CBDFHarness::MakeBDFFontL()
sl@0
   132
	{
sl@0
   133
	TOpenFontFaceAttrib attrib;
sl@0
   134
	iStandardFont->GetFaceAttrib(attrib);
sl@0
   135
	TPtrC familyName = attrib.FamilyName();
sl@0
   136
	TPtrC fullName = attrib.LocalFullName();
sl@0
   137
	TOpenFontMetrics fMetrics;
sl@0
   138
	iStandardFont->GetFontMetrics(fMetrics);
sl@0
   139
	iPPEM = fMetrics.Size();
sl@0
   140
sl@0
   141
	// Open file session
sl@0
   142
	RFs file_session;
sl@0
   143
	User::LeaveIfError(file_session.Connect());
sl@0
   144
	file_session.MkDir(_L("\\BDFfonts\\"));
sl@0
   145
	// Open file
sl@0
   146
	RFile file;
sl@0
   147
	buffer.Format(_L("\\BDFfonts\\%S %d.bdf"), &fullName, iPPEM);
sl@0
   148
	file.Replace(file_session, buffer, EFileShareAny);
sl@0
   149
	// Extract global info
sl@0
   150
	// STARTFONT 2.2
sl@0
   151
	buffer.Format(_L("STARTFONT 2.2\r\n"));
sl@0
   152
	FileWrite8(file, buffer);
sl@0
   153
	// COMMENT <font name> [(Bold) ][(Italic) ]at <nn> pixels per em
sl@0
   154
	buffer.Format(_L("COMMENT %S "), &familyName);
sl@0
   155
	FileWrite8(file, buffer);
sl@0
   156
	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
sl@0
   157
		{
sl@0
   158
		buffer.Format(_L("(Bold) "));
sl@0
   159
		FileWrite8(file, buffer);
sl@0
   160
		}
sl@0
   161
	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
sl@0
   162
		{
sl@0
   163
		buffer.Format(_L("(Italic) "));
sl@0
   164
		FileWrite8(file, buffer);
sl@0
   165
		}
sl@0
   166
	buffer.Format(_L("at %d pixels per em\r\n"), iPPEM);
sl@0
   167
	FileWrite8(file, buffer);
sl@0
   168
	// COMMENT Generated by the EPOC BDF creator
sl@0
   169
	buffer.Format(_L("COMMENT Generated by the EPOC BDF creator\r\n"));
sl@0
   170
	FileWrite8(file, buffer);
sl@0
   171
	// FONT <font name>
sl@0
   172
	buffer.Format(_L("FONT %S\r\n"), &iFilename);
sl@0
   173
	FileWrite8(file, buffer);
sl@0
   174
	// SIZE <ppem> 72 72
sl@0
   175
	buffer.Format(_L("SIZE %d 72 72\r\n"), iPPEM);
sl@0
   176
	FileWrite8(file, buffer);
sl@0
   177
	// FONTBOUNDINGBOX <bbox pixel width> <bbox pixel height> <bbox x pixel offset> <bbox y pixel offset>
sl@0
   178
	TInt bbw = fMetrics.MaxWidth();
sl@0
   179
	TInt bbh = fMetrics.MaxHeight() + fMetrics.MaxDepth();
sl@0
   180
	TInt bbxo = 0;
sl@0
   181
	TInt bbyo = -1 * fMetrics.MaxDepth();
sl@0
   182
	buffer.Format(_L("FONTBOUNDINGBOX %d %d %d %d\r\n"), bbw, bbh, bbxo, bbyo);
sl@0
   183
	FileWrite8(file, buffer);
sl@0
   184
	// STARTPROPERTIES
sl@0
   185
	TInt numproperties = 5;
sl@0
   186
	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
sl@0
   187
		numproperties++;
sl@0
   188
	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
sl@0
   189
		numproperties++;
sl@0
   190
	buffer.Format(_L("STARTPROPERTIES %d\r\n"), numproperties);
sl@0
   191
	FileWrite8(file, buffer);
sl@0
   192
	buffer.Format(_L("Uid %S\r\n"), &iUid);
sl@0
   193
	FileWrite8(file, buffer);
sl@0
   194
	buffer.Format(_L("MaxNormalCharWidth "));
sl@0
   195
	FileWrite8(file, buffer);
sl@0
   196
	TInt maxWidth = bbw;
sl@0
   197
	buffer.Format(_L("%d\r\n"), maxWidth);
sl@0
   198
	FileWrite8(file, buffer);
sl@0
   199
	buffer.Format(_L("MaxConsecutiveFillChars 5\r\n"));
sl@0
   200
	FileWrite8(file, buffer);
sl@0
   201
	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
sl@0
   202
		{
sl@0
   203
		buffer.Format(_L("Bold 1\r\n"));
sl@0
   204
		FileWrite8(file, buffer);
sl@0
   205
		}
sl@0
   206
	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
sl@0
   207
		{
sl@0
   208
		buffer.Format(_L("Italic 1\r\n"));
sl@0
   209
		FileWrite8(file, buffer);
sl@0
   210
		}
sl@0
   211
	// FONT_ASCENT
sl@0
   212
	buffer.Format(_L("FONT_ASCENT %d\r\n"), fMetrics.Ascent());
sl@0
   213
	FileWrite8(file, buffer);
sl@0
   214
	// FONT_DESCENT
sl@0
   215
	buffer.Format(_L("FONT_DESCENT %d\r\n"), fMetrics.Descent());
sl@0
   216
	FileWrite8(file, buffer);
sl@0
   217
	// ENDPROPERTIES
sl@0
   218
	buffer.Format(_L("ENDPROPERTIES\r\n"));
sl@0
   219
	FileWrite8(file, buffer);
sl@0
   220
	// CHARS <number of glyphs>
sl@0
   221
	// Work out how many chars in font
sl@0
   222
	TInt charCount = 0;
sl@0
   223
	TInt i = 0;
sl@0
   224
	for ( i = 0; i <= 0xFFFF; i++ )
sl@0
   225
		{
sl@0
   226
		if ( iStandardFont->HasCharacter(i) )
sl@0
   227
			charCount++;
sl@0
   228
		}
sl@0
   229
	buffer.Format(_L("CHARS %d\r\n"), charCount);
sl@0
   230
	FileWrite8(file, buffer);
sl@0
   231
sl@0
   232
	for ( i = 0; i <= 0xFFFF; i++ )
sl@0
   233
		{
sl@0
   234
		if ( iStandardFont->HasCharacter(i) )
sl@0
   235
			{
sl@0
   236
			// STARTCHAR <Unn in hex>
sl@0
   237
			buffer.Format(_L("STARTCHAR U%x\r\n"), i);
sl@0
   238
			FileWrite8(file, buffer);
sl@0
   239
			// ENCODING <usually nn decimal>
sl@0
   240
			buffer.Format(_L("ENCODING %d\r\n"), i);
sl@0
   241
			FileWrite8(file, buffer);
sl@0
   242
			// SWIDTH <swidth> 0
sl@0
   243
			// DWIDTH <swidth * (pointsize / 1000) * (device resolution / 72)> 0
sl@0
   244
			// DWIDTH <swidth * (ppem / 1000) * (72 / 72)> 0
sl@0
   245
			// but DWIDTH  = <advance in pixels> which we know
sl@0
   246
			// so SWIDTH = (DWIDTH * 1000) / ppem
sl@0
   247
			TOpenFontCharMetrics cMetrics;
sl@0
   248
			const TUint8* bitmapPtr;
sl@0
   249
			TSize dummy;
sl@0
   250
			iStandardFont->GetCharacterData(i, cMetrics, bitmapPtr, dummy);
sl@0
   251
			TInt dwidth = cMetrics.HorizAdvance();
sl@0
   252
			TReal dwidthReal = dwidth;
sl@0
   253
			TInt swidth = (TInt)(((dwidthReal * 1000) / iPPEM) + 0.5);
sl@0
   254
			buffer.Format(_L("SWIDTH %d 0\r\n"), swidth);
sl@0
   255
			FileWrite8(file, buffer);
sl@0
   256
			buffer.Format(_L("DWIDTH %d 0\r\n"), dwidth);
sl@0
   257
			FileWrite8(file, buffer);
sl@0
   258
			// BBX <bmap pixel width> <bmap pixel height> <bmap x pixel offset> <bmap y pixel offset>
sl@0
   259
			TInt bpw = cMetrics.Width();
sl@0
   260
			TInt bph = cMetrics.Height();
sl@0
   261
			TInt bxo = cMetrics.HorizBearingX();
sl@0
   262
			TInt byo = cMetrics.HorizBearingY() - bph; // Because openfont offsets are to top left and bdf is to bottom left
sl@0
   263
			buffer.Format(_L("BBX %d %d %d %d\r\n"), bpw, bph, bxo, byo);
sl@0
   264
			FileWrite8(file, buffer);
sl@0
   265
			// BITMAP
sl@0
   266
			buffer.Format(_L("BITMAP\r\n"));
sl@0
   267
			FileWrite8(file, buffer);
sl@0
   268
			TInt paddedWidth = ((bpw + 7) / 8);
sl@0
   269
			if (bph * paddedWidth)
sl@0
   270
				{
sl@0
   271
				TUint8* bitmap = new TUint8 [sizeof(TUint8) * bph * paddedWidth];
sl@0
   272
				DecodeBitmap(bpw, paddedWidth, bph, bitmapPtr, bitmap);
sl@0
   273
				for (TInt j = 0; j < bph; j++)
sl@0
   274
					{
sl@0
   275
					// Output one line of bitmap
sl@0
   276
#ifndef SHOW_FONT_PICTURES_INSTEAD_OF_HEX
sl@0
   277
					// This branch is the standard version that produces useable BDF files
sl@0
   278
					for (TInt k = paddedWidth - 1; k >= 0; k--)
sl@0
   279
						{
sl@0
   280
						TInt byte = *(bitmap + (j * paddedWidth) + k);
sl@0
   281
sl@0
   282
						OutHex(byte / 16);
sl@0
   283
						FileWrite8(file, buffer);
sl@0
   284
						OutHex(byte % 16);
sl@0
   285
						FileWrite8(file, buffer);
sl@0
   286
						}
sl@0
   287
					buffer.Format(_L("\r\n"));
sl@0
   288
					FileWrite8(file, buffer);
sl@0
   289
#else
sl@0
   290
					// This branch shows the char bitmaps but does not produce useable BDF files
sl@0
   291
					buffer.Format(_L("["));
sl@0
   292
					FileWrite8(file, buffer);
sl@0
   293
					iBitNum = ((j + 1) * paddedWidth * 8) - 1;
sl@0
   294
					iBitMap = bitmap;
sl@0
   295
sl@0
   296
					for (TInt k = 0; k < bpw; k++)
sl@0
   297
						{
sl@0
   298
						if (ReadBitBack())
sl@0
   299
							buffer.Format(_L("@"));
sl@0
   300
						else
sl@0
   301
							buffer.Format(_L(" "));
sl@0
   302
						FileWrite8(file, buffer);
sl@0
   303
						}
sl@0
   304
					for (k = bpw; k < 8 * paddedWidth; k++)
sl@0
   305
						{
sl@0
   306
						buffer.Format(_L("."));
sl@0
   307
						FileWrite8(file, buffer);
sl@0
   308
						}
sl@0
   309
					buffer.Format(_L("]\r\n"));
sl@0
   310
					FileWrite8(file, buffer);
sl@0
   311
#endif
sl@0
   312
					}
sl@0
   313
				delete [] bitmap;
sl@0
   314
				}
sl@0
   315
			// ENDCHAR
sl@0
   316
			buffer.Format(_L("ENDCHAR\r\n"));
sl@0
   317
			FileWrite8(file, buffer);
sl@0
   318
			}
sl@0
   319
		}
sl@0
   320
	// ENDFONT
sl@0
   321
	buffer.Format(_L("ENDFONT\r\n"));
sl@0
   322
	FileWrite8(file, buffer);
sl@0
   323
	// Close file
sl@0
   324
	file.Flush();
sl@0
   325
	file.Close();
sl@0
   326
	file_session.Close();
sl@0
   327
sl@0
   328
	}
sl@0
   329
sl@0
   330
TInt CBDFHarness::ReadBit()
sl@0
   331
	{
sl@0
   332
	TInt val = 1;
sl@0
   333
	for (TInt i = 0; i < (iBitNum % 8); i++)
sl@0
   334
		val *= 2;
sl@0
   335
	val = iBitMap[iBitNum / 8] & val;
sl@0
   336
	iBitNum++;
sl@0
   337
	return val ? 1 : 0;
sl@0
   338
	}
sl@0
   339
sl@0
   340
TInt CBDFHarness::ReadBitBack()
sl@0
   341
	{
sl@0
   342
	TInt val = 1;
sl@0
   343
	for (TInt i = 0; i < (iBitNum % 8); i++)
sl@0
   344
		val *= 2;
sl@0
   345
	val = iBitMap[iBitNum / 8] & val;
sl@0
   346
	iBitNum--;
sl@0
   347
	return val ? 1 : 0;
sl@0
   348
	}
sl@0
   349
sl@0
   350
void CBDFHarness::OutHex(TInt aOneHexDigit)
sl@0
   351
	{
sl@0
   352
	if (aOneHexDigit <= 9)
sl@0
   353
		buffer.Format(_L("%c"), '0' + aOneHexDigit);
sl@0
   354
	else
sl@0
   355
		buffer.Format(_L("%c"), 'a' + aOneHexDigit - 10);
sl@0
   356
	}
sl@0
   357
sl@0
   358
void CBDFHarness::DecodeBitmap(TInt aWidth, TInt aPaddedWidth, TInt aHeight, const TUint8* aCodedBitmap, TUint8* aBitMap)
sl@0
   359
	{
sl@0
   360
	// Zero the bitmap
sl@0
   361
	for (TInt i = 0; i < aPaddedWidth * aHeight; i++)
sl@0
   362
		aBitMap[i] = 0;
sl@0
   363
	TInt repeats = 0;
sl@0
   364
	iBitNum = 0;
sl@0
   365
	iBitMap = aCodedBitmap;
sl@0
   366
	for (TInt linesRead = 0; linesRead < aHeight; linesRead += repeats)
sl@0
   367
		{
sl@0
   368
		TInt repeating = !(ReadBit());
sl@0
   369
		
sl@0
   370
		// Intended behavior is for the line of code below to be evaluated left to right.
sl@0
   371
		//    repeats = (1 * ReadBit()) + (2 * ReadBit()) + (4 * ReadBit()) + (8 * ReadBit());
sl@0
   372
		// However, the order in which calls to ReadBit() above are evaluated is undefined,
sl@0
   373
		// and is compiler dependent.
sl@0
   374
		// The following code ensures that the correct code is used:
sl@0
   375
		TInt bit1 = ReadBit();
sl@0
   376
		TInt bit2 = ReadBit();
sl@0
   377
		TInt bit3 = ReadBit();
sl@0
   378
		TInt bit4 = ReadBit();
sl@0
   379
		repeats = (1 * bit1) + (2 * bit2) + (4 * bit3) + (8 * bit4);
sl@0
   380
sl@0
   381
		TInt padVal = (aPaddedWidth * 8) - aWidth;
sl@0
   382
		if (repeating)
sl@0
   383
			{
sl@0
   384
			for (TInt j = padVal + aWidth - 1; j >= padVal; j--)
sl@0
   385
				{
sl@0
   386
				TInt value = ReadBit();
sl@0
   387
				for (TInt k = 0; k < (j % 8); k++)
sl@0
   388
					value *= 2;
sl@0
   389
				for (TInt l = 0; l < repeats; l++)
sl@0
   390
					{
sl@0
   391
					aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] =
sl@0
   392
						TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value);
sl@0
   393
					}
sl@0
   394
				}
sl@0
   395
			}
sl@0
   396
		else
sl@0
   397
			{
sl@0
   398
			for (TInt l = 0; l < repeats; l++)
sl@0
   399
				{
sl@0
   400
				for (TInt j = padVal + aWidth - 1; j >= padVal; j--)
sl@0
   401
					{
sl@0
   402
					TInt value = ReadBit();
sl@0
   403
					for (TInt k = 0; k < (j % 8); k++)
sl@0
   404
						value *= 2;
sl@0
   405
					aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] =
sl@0
   406
						TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value);
sl@0
   407
					}
sl@0
   408
				}
sl@0
   409
			}
sl@0
   410
		}
sl@0
   411
	}
sl@0
   412