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 +