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