1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Foundation code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2005-2009
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Stuart Parmenter <stuart@mozilla.com>
23 : * John Daggett <jdaggett@mozilla.com>
24 : * Jonathan Kew <jfkthame@gmail.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef GFX_FONT_UTILS_H
41 : #define GFX_FONT_UTILS_H
42 :
43 : #include "gfxTypes.h"
44 : #include "gfxPlatform.h"
45 :
46 : #include "prtypes.h"
47 : #include "nsAlgorithm.h"
48 : #include "prcpucfg.h"
49 :
50 : #include "nsDataHashtable.h"
51 :
52 : #include "nsITimer.h"
53 : #include "nsCOMPtr.h"
54 : #include "nsIRunnable.h"
55 : #include "nsThreadUtils.h"
56 : #include "nsComponentManagerUtils.h"
57 : #include "nsTArray.h"
58 : #include "nsAutoPtr.h"
59 : #include "nsIStreamBufferAccess.h"
60 :
61 : /* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
62 : #ifdef __MINGW32__
63 : #undef min
64 : #undef max
65 : #endif
66 :
67 0 : class gfxSparseBitSet {
68 : private:
69 : enum { BLOCK_SIZE = 32 }; // ==> 256 codepoints per block
70 : enum { BLOCK_SIZE_BITS = BLOCK_SIZE * 8 };
71 : enum { BLOCK_INDEX_SHIFT = 8 };
72 :
73 : struct Block {
74 0 : Block(const Block& aBlock) { memcpy(mBits, aBlock.mBits, sizeof(mBits)); }
75 0 : Block(unsigned char memsetValue = 0) { memset(mBits, memsetValue, BLOCK_SIZE); }
76 : PRUint8 mBits[BLOCK_SIZE];
77 : };
78 :
79 : public:
80 0 : gfxSparseBitSet() { }
81 : gfxSparseBitSet(const gfxSparseBitSet& aBitset) {
82 : PRUint32 len = aBitset.mBlocks.Length();
83 : mBlocks.AppendElements(len);
84 : for (PRUint32 i = 0; i < len; ++i) {
85 : Block *block = aBitset.mBlocks[i];
86 : if (block)
87 : mBlocks[i] = new Block(*block);
88 : }
89 : }
90 0 : bool test(PRUint32 aIndex) const {
91 0 : NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
92 0 : PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
93 0 : if (blockIndex >= mBlocks.Length())
94 0 : return false;
95 0 : Block *block = mBlocks[blockIndex];
96 0 : if (!block)
97 0 : return false;
98 0 : return ((block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0;
99 : }
100 :
101 : #if PR_LOGGING
102 : // dump out contents of bitmap
103 : void Dump(const char* aPrefix, eGfxLog aWhichLog) const;
104 : #endif
105 :
106 : bool TestRange(PRUint32 aStart, PRUint32 aEnd) {
107 : PRUint32 startBlock, endBlock, blockLen;
108 :
109 : // start point is beyond the end of the block array? return false immediately
110 : startBlock = aStart >> BLOCK_INDEX_SHIFT;
111 : blockLen = mBlocks.Length();
112 : if (startBlock >= blockLen) return false;
113 :
114 : // check for blocks in range, if none, return false
115 : PRUint32 blockIndex;
116 : bool hasBlocksInRange = false;
117 :
118 : endBlock = aEnd >> BLOCK_INDEX_SHIFT;
119 : blockIndex = startBlock;
120 : for (blockIndex = startBlock; blockIndex <= endBlock; blockIndex++) {
121 : if (blockIndex < blockLen && mBlocks[blockIndex])
122 : hasBlocksInRange = true;
123 : }
124 : if (!hasBlocksInRange) return false;
125 :
126 : Block *block;
127 : PRUint32 i, start, end;
128 :
129 : // first block, check bits
130 : if ((block = mBlocks[startBlock])) {
131 : start = aStart;
132 : end = NS_MIN(aEnd, ((startBlock+1) << BLOCK_INDEX_SHIFT) - 1);
133 : for (i = start; i <= end; i++) {
134 : if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7)))
135 : return true;
136 : }
137 : }
138 : if (endBlock == startBlock) return false;
139 :
140 : // [2..n-1] blocks check bytes
141 : for (blockIndex = startBlock + 1; blockIndex < endBlock; blockIndex++) {
142 : PRUint32 index;
143 :
144 : if (blockIndex >= blockLen || !(block = mBlocks[blockIndex])) continue;
145 : for (index = 0; index < BLOCK_SIZE; index++) {
146 : if (block->mBits[index])
147 : return true;
148 : }
149 : }
150 :
151 : // last block, check bits
152 : if (endBlock < blockLen && (block = mBlocks[endBlock])) {
153 : start = endBlock << BLOCK_INDEX_SHIFT;
154 : end = aEnd;
155 : for (i = start; i <= end; i++) {
156 : if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7)))
157 : return true;
158 : }
159 : }
160 :
161 : return false;
162 : }
163 :
164 0 : void set(PRUint32 aIndex) {
165 0 : PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
166 0 : if (blockIndex >= mBlocks.Length()) {
167 0 : nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
168 0 : if (NS_UNLIKELY(!blocks)) // OOM
169 0 : return;
170 : }
171 0 : Block *block = mBlocks[blockIndex];
172 0 : if (!block) {
173 0 : block = new Block;
174 0 : mBlocks[blockIndex] = block;
175 : }
176 0 : block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
177 : }
178 :
179 : void set(PRUint32 aIndex, bool aValue) {
180 : if (aValue)
181 : set(aIndex);
182 : else
183 : clear(aIndex);
184 : }
185 :
186 0 : void SetRange(PRUint32 aStart, PRUint32 aEnd) {
187 0 : const PRUint32 startIndex = aStart/BLOCK_SIZE_BITS;
188 0 : const PRUint32 endIndex = aEnd/BLOCK_SIZE_BITS;
189 :
190 0 : if (endIndex >= mBlocks.Length()) {
191 0 : PRUint32 numNewBlocks = endIndex + 1 - mBlocks.Length();
192 0 : nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks);
193 0 : if (NS_UNLIKELY(!blocks)) // OOM
194 0 : return;
195 : }
196 :
197 0 : for (PRUint32 i = startIndex; i <= endIndex; ++i) {
198 0 : const PRUint32 blockFirstBit = i * BLOCK_SIZE_BITS;
199 0 : const PRUint32 blockLastBit = blockFirstBit + BLOCK_SIZE_BITS - 1;
200 :
201 0 : Block *block = mBlocks[i];
202 0 : if (!block) {
203 0 : bool fullBlock = false;
204 0 : if (aStart <= blockFirstBit && aEnd >= blockLastBit)
205 0 : fullBlock = true;
206 :
207 0 : block = new Block(fullBlock ? 0xFF : 0);
208 0 : mBlocks[i] = block;
209 :
210 0 : if (fullBlock)
211 0 : continue;
212 : }
213 :
214 0 : const PRUint32 start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
215 0 : const PRUint32 end = NS_MIN<PRUint32>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
216 :
217 0 : for (PRUint32 bit = start; bit <= end; ++bit) {
218 0 : block->mBits[bit>>3] |= 1 << (bit & 0x7);
219 : }
220 : }
221 : }
222 :
223 : void clear(PRUint32 aIndex) {
224 : PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
225 : if (blockIndex >= mBlocks.Length()) {
226 : nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
227 : if (NS_UNLIKELY(!blocks)) // OOM
228 : return;
229 : }
230 : Block *block = mBlocks[blockIndex];
231 : if (!block) {
232 : return;
233 : }
234 : block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] &= ~(1 << (aIndex & 0x7));
235 : }
236 :
237 : void ClearRange(PRUint32 aStart, PRUint32 aEnd) {
238 : const PRUint32 startIndex = aStart/BLOCK_SIZE_BITS;
239 : const PRUint32 endIndex = aEnd/BLOCK_SIZE_BITS;
240 :
241 : if (endIndex >= mBlocks.Length()) {
242 : PRUint32 numNewBlocks = endIndex + 1 - mBlocks.Length();
243 : nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks);
244 : if (NS_UNLIKELY(!blocks)) // OOM
245 : return;
246 : }
247 :
248 : for (PRUint32 i = startIndex; i <= endIndex; ++i) {
249 : const PRUint32 blockFirstBit = i * BLOCK_SIZE_BITS;
250 :
251 : Block *block = mBlocks[i];
252 : if (!block) {
253 : // any nonexistent block is implicitly all clear,
254 : // so there's no need to even create it
255 : continue;
256 : }
257 :
258 : const PRUint32 start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
259 : const PRUint32 end = NS_MIN<PRUint32>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
260 :
261 : for (PRUint32 bit = start; bit <= end; ++bit) {
262 : block->mBits[bit>>3] &= ~(1 << (bit & 0x7));
263 : }
264 : }
265 : }
266 :
267 : PRUint32 GetSize() {
268 : PRUint32 size = 0;
269 : for (PRUint32 i = 0; i < mBlocks.Length(); i++) {
270 : if (mBlocks[i])
271 : size += sizeof(Block);
272 : size += sizeof(nsAutoPtr<Block>);
273 : }
274 : return size;
275 : }
276 :
277 : // clear out all blocks in the array
278 0 : void reset() {
279 : PRUint32 i;
280 0 : for (i = 0; i < mBlocks.Length(); i++)
281 0 : mBlocks[i] = nsnull;
282 0 : }
283 :
284 : // set this bitset to the union of its current contents and another
285 0 : void Union(const gfxSparseBitSet& aBitset) {
286 : // ensure mBlocks is large enough
287 0 : PRUint32 blockCount = aBitset.mBlocks.Length();
288 0 : if (blockCount > mBlocks.Length()) {
289 0 : PRUint32 needed = blockCount - mBlocks.Length();
290 0 : nsAutoPtr<Block> *blocks = mBlocks.AppendElements(needed);
291 0 : if (NS_UNLIKELY(!blocks)) { // OOM
292 0 : return;
293 : }
294 : }
295 : // for each block that may be present in aBitset...
296 0 : for (PRUint32 i = 0; i < blockCount; ++i) {
297 : // if it is missing (implicitly empty), just skip
298 0 : if (!aBitset.mBlocks[i]) {
299 0 : continue;
300 : }
301 : // if the block is missing in this set, just copy the other
302 0 : if (!mBlocks[i]) {
303 0 : mBlocks[i] = new Block(*aBitset.mBlocks[i]);
304 0 : continue;
305 : }
306 : // else set existing block to the union of both
307 0 : PRUint32 *dst = reinterpret_cast<PRUint32*>(mBlocks[i]->mBits);
308 : const PRUint32 *src =
309 0 : reinterpret_cast<const PRUint32*>(aBitset.mBlocks[i]->mBits);
310 0 : for (PRUint32 j = 0; j < BLOCK_SIZE / 4; ++j) {
311 0 : dst[j] |= src[j];
312 : }
313 : }
314 : }
315 :
316 0 : void Compact() {
317 0 : mBlocks.Compact();
318 0 : }
319 :
320 : private:
321 : nsTArray< nsAutoPtr<Block> > mBlocks;
322 : };
323 :
324 : #define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
325 :
326 : namespace mozilla {
327 :
328 : // Byte-swapping types and name table structure definitions moved from
329 : // gfxFontUtils.cpp to .h file so that gfxFont.cpp can also refer to them
330 : #pragma pack(1)
331 :
332 : struct AutoSwap_PRUint16 {
333 : #ifdef __SUNPRO_CC
334 : AutoSwap_PRUint16& operator = (const PRUint16 aValue)
335 : { this->value = NS_SWAP16(aValue); return *this; }
336 : #else
337 0 : AutoSwap_PRUint16(PRUint16 aValue) { value = NS_SWAP16(aValue); }
338 : #endif
339 0 : operator PRUint16() const { return NS_SWAP16(value); }
340 0 : operator PRUint32() const { return NS_SWAP16(value); }
341 0 : operator PRUint64() const { return NS_SWAP16(value); }
342 : PRUint16 value;
343 : };
344 :
345 : struct AutoSwap_PRInt16 {
346 : #ifdef __SUNPRO_CC
347 : AutoSwap_PRInt16& operator = (const PRInt16 aValue)
348 : { this->value = NS_SWAP16(aValue); return *this; }
349 : #else
350 : AutoSwap_PRInt16(PRInt16 aValue) { value = NS_SWAP16(aValue); }
351 : #endif
352 0 : operator PRInt16() const { return NS_SWAP16(value); }
353 : operator PRUint32() const { return NS_SWAP16(value); }
354 : PRInt16 value;
355 : };
356 :
357 : struct AutoSwap_PRUint32 {
358 : #ifdef __SUNPRO_CC
359 : AutoSwap_PRUint32& operator = (const PRUint32 aValue)
360 : { this->value = NS_SWAP32(aValue); return *this; }
361 : #else
362 0 : AutoSwap_PRUint32(PRUint32 aValue) { value = NS_SWAP32(aValue); }
363 : #endif
364 0 : operator PRUint32() const { return NS_SWAP32(value); }
365 : PRUint32 value;
366 : };
367 :
368 : struct AutoSwap_PRInt32 {
369 : #ifdef __SUNPRO_CC
370 : AutoSwap_PRInt32& operator = (const PRInt32 aValue)
371 : { this->value = NS_SWAP32(aValue); return *this; }
372 : #else
373 : AutoSwap_PRInt32(PRInt32 aValue) { value = NS_SWAP32(aValue); }
374 : #endif
375 : operator PRInt32() const { return NS_SWAP32(value); }
376 : PRInt32 value;
377 : };
378 :
379 : struct AutoSwap_PRUint64 {
380 : #ifdef __SUNPRO_CC
381 : AutoSwap_PRUint64& operator = (const PRUint64 aValue)
382 : { this->value = NS_SWAP64(aValue); return *this; }
383 : #else
384 : AutoSwap_PRUint64(PRUint64 aValue) { value = NS_SWAP64(aValue); }
385 : #endif
386 : operator PRUint64() const { return NS_SWAP64(value); }
387 : PRUint64 value;
388 : };
389 :
390 : struct AutoSwap_PRUint24 {
391 0 : operator PRUint32() const { return value[0] << 16 | value[1] << 8 | value[2]; }
392 : private:
393 : AutoSwap_PRUint24() { }
394 : PRUint8 value[3];
395 : };
396 :
397 : struct SFNTHeader {
398 : AutoSwap_PRUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0.
399 : AutoSwap_PRUint16 numTables; // Number of tables.
400 : AutoSwap_PRUint16 searchRange; // (Maximum power of 2 <= numTables) x 16.
401 : AutoSwap_PRUint16 entrySelector; // Log2(maximum power of 2 <= numTables).
402 : AutoSwap_PRUint16 rangeShift; // NumTables x 16-searchRange.
403 : };
404 :
405 : struct TableDirEntry {
406 : AutoSwap_PRUint32 tag; // 4 -byte identifier.
407 : AutoSwap_PRUint32 checkSum; // CheckSum for this table.
408 : AutoSwap_PRUint32 offset; // Offset from beginning of TrueType font file.
409 : AutoSwap_PRUint32 length; // Length of this table.
410 : };
411 :
412 : struct HeadTable {
413 : enum {
414 : HEAD_VERSION = 0x00010000,
415 : HEAD_MAGIC_NUMBER = 0x5F0F3CF5,
416 : HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA
417 : };
418 :
419 : AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0.
420 : AutoSwap_PRUint32 fontRevision; // Set by font manufacturer.
421 : AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
422 : AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5.
423 : AutoSwap_PRUint16 flags;
424 : AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
425 : AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
426 : AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
427 : AutoSwap_PRInt16 xMin; // For all glyph bounding boxes.
428 : AutoSwap_PRInt16 yMin; // For all glyph bounding boxes.
429 : AutoSwap_PRInt16 xMax; // For all glyph bounding boxes.
430 : AutoSwap_PRInt16 yMax; // For all glyph bounding boxes.
431 : AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1);
432 : AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels.
433 : AutoSwap_PRInt16 fontDirectionHint;
434 : AutoSwap_PRInt16 indexToLocFormat;
435 : AutoSwap_PRInt16 glyphDataFormat;
436 : };
437 :
438 : struct OS2Table {
439 : AutoSwap_PRUint16 version; // 0004 = OpenType 1.5
440 : AutoSwap_PRInt16 xAvgCharWidth;
441 : AutoSwap_PRUint16 usWeightClass;
442 : AutoSwap_PRUint16 usWidthClass;
443 : AutoSwap_PRUint16 fsType;
444 : AutoSwap_PRInt16 ySubscriptXSize;
445 : AutoSwap_PRInt16 ySubscriptYSize;
446 : AutoSwap_PRInt16 ySubscriptXOffset;
447 : AutoSwap_PRInt16 ySubscriptYOffset;
448 : AutoSwap_PRInt16 ySuperscriptXSize;
449 : AutoSwap_PRInt16 ySuperscriptYSize;
450 : AutoSwap_PRInt16 ySuperscriptXOffset;
451 : AutoSwap_PRInt16 ySuperscriptYOffset;
452 : AutoSwap_PRInt16 yStrikeoutSize;
453 : AutoSwap_PRInt16 yStrikeoutPosition;
454 : AutoSwap_PRInt16 sFamilyClass;
455 : PRUint8 panose[10];
456 : AutoSwap_PRUint32 unicodeRange1;
457 : AutoSwap_PRUint32 unicodeRange2;
458 : AutoSwap_PRUint32 unicodeRange3;
459 : AutoSwap_PRUint32 unicodeRange4;
460 : PRUint8 achVendID[4];
461 : AutoSwap_PRUint16 fsSelection;
462 : AutoSwap_PRUint16 usFirstCharIndex;
463 : AutoSwap_PRUint16 usLastCharIndex;
464 : AutoSwap_PRInt16 sTypoAscender;
465 : AutoSwap_PRInt16 sTypoDescender;
466 : AutoSwap_PRInt16 sTypoLineGap;
467 : AutoSwap_PRUint16 usWinAscent;
468 : AutoSwap_PRUint16 usWinDescent;
469 : AutoSwap_PRUint32 codePageRange1;
470 : AutoSwap_PRUint32 codePageRange2;
471 : AutoSwap_PRInt16 sxHeight;
472 : AutoSwap_PRInt16 sCapHeight;
473 : AutoSwap_PRUint16 usDefaultChar;
474 : AutoSwap_PRUint16 usBreakChar;
475 : AutoSwap_PRUint16 usMaxContext;
476 : };
477 :
478 : struct PostTable {
479 : AutoSwap_PRUint32 version;
480 : AutoSwap_PRInt32 italicAngle;
481 : AutoSwap_PRInt16 underlinePosition;
482 : AutoSwap_PRUint16 underlineThickness;
483 : AutoSwap_PRUint32 isFixedPitch;
484 : AutoSwap_PRUint32 minMemType42;
485 : AutoSwap_PRUint32 maxMemType42;
486 : AutoSwap_PRUint32 minMemType1;
487 : AutoSwap_PRUint32 maxMemType1;
488 : };
489 :
490 : struct HheaTable {
491 : AutoSwap_PRUint32 version;
492 : AutoSwap_PRInt16 ascender;
493 : AutoSwap_PRInt16 descender;
494 : AutoSwap_PRInt16 lineGap;
495 : AutoSwap_PRUint16 advanceWidthMax;
496 : AutoSwap_PRInt16 minLeftSideBearing;
497 : AutoSwap_PRInt16 minRightSideBearing;
498 : AutoSwap_PRInt16 xMaxExtent;
499 : AutoSwap_PRInt16 caretSlopeRise;
500 : AutoSwap_PRInt16 caretSlopeRun;
501 : AutoSwap_PRInt16 caretOffset;
502 : AutoSwap_PRInt16 reserved1;
503 : AutoSwap_PRInt16 reserved2;
504 : AutoSwap_PRInt16 reserved3;
505 : AutoSwap_PRInt16 reserved4;
506 : AutoSwap_PRInt16 metricDataFormat;
507 : AutoSwap_PRUint16 numOfLongHorMetrics;
508 : };
509 :
510 : struct MaxpTableHeader {
511 : AutoSwap_PRUint32 version; // CFF: 0x00005000; TrueType: 0x00010000
512 : AutoSwap_PRUint16 numGlyphs;
513 : // truetype version has additional fields that we don't currently use
514 : };
515 :
516 : // old 'kern' table, supported on Windows
517 : // see http://www.microsoft.com/typography/otspec/kern.htm
518 : struct KernTableVersion0 {
519 : AutoSwap_PRUint16 version; // 0x0000
520 : AutoSwap_PRUint16 nTables;
521 : };
522 :
523 : struct KernTableSubtableHeaderVersion0 {
524 : AutoSwap_PRUint16 version;
525 : AutoSwap_PRUint16 length;
526 : AutoSwap_PRUint16 coverage;
527 : };
528 :
529 : // newer Mac-only 'kern' table, ignored by Windows
530 : // see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6kern.html
531 : struct KernTableVersion1 {
532 : AutoSwap_PRUint32 version; // 0x00010000
533 : AutoSwap_PRUint32 nTables;
534 : };
535 :
536 : struct KernTableSubtableHeaderVersion1 {
537 : AutoSwap_PRUint32 length;
538 : AutoSwap_PRUint16 coverage;
539 : AutoSwap_PRUint16 tupleIndex;
540 : };
541 :
542 : #pragma pack()
543 :
544 : // Return just the highest bit of the given value, i.e., the highest
545 : // power of 2 that is <= value, or zero if the input value is zero.
546 : inline PRUint32
547 0 : FindHighestBit(PRUint32 value)
548 : {
549 : // propagate highest bit into all lower bits of the value
550 0 : value |= (value >> 1);
551 0 : value |= (value >> 2);
552 0 : value |= (value >> 4);
553 0 : value |= (value >> 8);
554 0 : value |= (value >> 16);
555 : // isolate the leftmost bit
556 0 : return (value & ~(value >> 1));
557 : }
558 :
559 : } // namespace mozilla
560 :
561 : // used for overlaying name changes without touching original font data
562 : struct FontDataOverlay {
563 : // overlaySrc != 0 ==> use overlay
564 : PRUint32 overlaySrc; // src offset from start of font data
565 : PRUint32 overlaySrcLen; // src length
566 : PRUint32 overlayDest; // dest offset from start of font data
567 : };
568 :
569 : enum gfxUserFontType {
570 : GFX_USERFONT_UNKNOWN = 0,
571 : GFX_USERFONT_OPENTYPE = 1,
572 : GFX_USERFONT_SVG = 2,
573 : GFX_USERFONT_WOFF = 3
574 : };
575 :
576 : class THEBES_API gfxFontUtils {
577 :
578 : public:
579 : // these are public because gfxFont.cpp also looks into the name table
580 : enum {
581 : NAME_ID_FAMILY = 1,
582 : NAME_ID_STYLE = 2,
583 : NAME_ID_UNIQUE = 3,
584 : NAME_ID_FULL = 4,
585 : NAME_ID_VERSION = 5,
586 : NAME_ID_POSTSCRIPT = 6,
587 : NAME_ID_PREFERRED_FAMILY = 16,
588 : NAME_ID_PREFERRED_STYLE = 17,
589 :
590 : PLATFORM_ALL = -1,
591 : PLATFORM_ID_UNICODE = 0, // Mac OS uses this typically
592 : PLATFORM_ID_MAC = 1,
593 : PLATFORM_ID_ISO = 2,
594 : PLATFORM_ID_MICROSOFT = 3,
595 :
596 : ENCODING_ID_MAC_ROMAN = 0, // traditional Mac OS script manager encodings
597 : ENCODING_ID_MAC_JAPANESE = 1, // (there are others defined, but some were never
598 : ENCODING_ID_MAC_TRAD_CHINESE = 2, // implemented by Apple, and I have never seen them
599 : ENCODING_ID_MAC_KOREAN = 3, // used in font names)
600 : ENCODING_ID_MAC_ARABIC = 4,
601 : ENCODING_ID_MAC_HEBREW = 5,
602 : ENCODING_ID_MAC_GREEK = 6,
603 : ENCODING_ID_MAC_CYRILLIC = 7,
604 : ENCODING_ID_MAC_DEVANAGARI = 9,
605 : ENCODING_ID_MAC_GURMUKHI = 10,
606 : ENCODING_ID_MAC_GUJARATI = 11,
607 : ENCODING_ID_MAC_SIMP_CHINESE = 25,
608 :
609 : ENCODING_ID_MICROSOFT_SYMBOL = 0, // Microsoft platform encoding IDs
610 : ENCODING_ID_MICROSOFT_UNICODEBMP = 1,
611 : ENCODING_ID_MICROSOFT_SHIFTJIS = 2,
612 : ENCODING_ID_MICROSOFT_PRC = 3,
613 : ENCODING_ID_MICROSOFT_BIG5 = 4,
614 : ENCODING_ID_MICROSOFT_WANSUNG = 5,
615 : ENCODING_ID_MICROSOFT_JOHAB = 6,
616 : ENCODING_ID_MICROSOFT_UNICODEFULL = 10,
617 :
618 : LANG_ALL = -1,
619 : LANG_ID_MAC_ENGLISH = 0, // many others are defined, but most don't affect
620 : LANG_ID_MAC_HEBREW = 10, // the charset; should check all the central/eastern
621 : LANG_ID_MAC_JAPANESE = 11, // european codes, though
622 : LANG_ID_MAC_ARABIC = 12,
623 : LANG_ID_MAC_ICELANDIC = 15,
624 : LANG_ID_MAC_TURKISH = 17,
625 : LANG_ID_MAC_TRAD_CHINESE = 19,
626 : LANG_ID_MAC_URDU = 20,
627 : LANG_ID_MAC_KOREAN = 23,
628 : LANG_ID_MAC_POLISH = 25,
629 : LANG_ID_MAC_FARSI = 31,
630 : LANG_ID_MAC_SIMP_CHINESE = 33,
631 : LANG_ID_MAC_ROMANIAN = 37,
632 : LANG_ID_MAC_CZECH = 38,
633 : LANG_ID_MAC_SLOVAK = 39,
634 :
635 : LANG_ID_MICROSOFT_EN_US = 0x0409, // with Microsoft platformID, EN US lang code
636 :
637 : CMAP_MAX_CODEPOINT = 0x10ffff // maximum possible Unicode codepoint
638 : // contained in a cmap
639 : };
640 :
641 : // name table has a header, followed by name records, followed by string data
642 : struct NameHeader {
643 : mozilla::AutoSwap_PRUint16 format; // Format selector (=0).
644 : mozilla::AutoSwap_PRUint16 count; // Number of name records.
645 : mozilla::AutoSwap_PRUint16 stringOffset; // Offset to start of string storage
646 : // (from start of table)
647 : };
648 :
649 : struct NameRecord {
650 : mozilla::AutoSwap_PRUint16 platformID; // Platform ID
651 : mozilla::AutoSwap_PRUint16 encodingID; // Platform-specific encoding ID
652 : mozilla::AutoSwap_PRUint16 languageID; // Language ID
653 : mozilla::AutoSwap_PRUint16 nameID; // Name ID.
654 : mozilla::AutoSwap_PRUint16 length; // String length (in bytes).
655 : mozilla::AutoSwap_PRUint16 offset; // String offset from start of storage
656 : // (in bytes).
657 : };
658 :
659 : // for reading big-endian font data on either big or little-endian platforms
660 :
661 : static inline PRUint16
662 0 : ReadShortAt(const PRUint8 *aBuf, PRUint32 aIndex)
663 : {
664 0 : return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
665 : }
666 :
667 : static inline PRUint16
668 0 : ReadShortAt16(const PRUint16 *aBuf, PRUint32 aIndex)
669 : {
670 0 : const PRUint8 *buf = reinterpret_cast<const PRUint8*>(aBuf);
671 0 : PRUint32 index = aIndex << 1;
672 0 : return (buf[index] << 8) | buf[index+1];
673 : }
674 :
675 : static inline PRUint32
676 0 : ReadUint24At(const PRUint8 *aBuf, PRUint32 aIndex)
677 : {
678 0 : return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) |
679 0 : (aBuf[aIndex + 2]));
680 : }
681 :
682 : static inline PRUint32
683 0 : ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
684 : {
685 0 : return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
686 0 : (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
687 : }
688 :
689 : static nsresult
690 : ReadCMAPTableFormat12(const PRUint8 *aBuf, PRUint32 aLength,
691 : gfxSparseBitSet& aCharacterMap);
692 :
693 : static nsresult
694 : ReadCMAPTableFormat4(const PRUint8 *aBuf, PRUint32 aLength,
695 : gfxSparseBitSet& aCharacterMap);
696 :
697 : static nsresult
698 : ReadCMAPTableFormat14(const PRUint8 *aBuf, PRUint32 aLength,
699 : PRUint8*& aTable);
700 :
701 : static PRUint32
702 : FindPreferredSubtable(const PRUint8 *aBuf, PRUint32 aBufLength,
703 : PRUint32 *aTableOffset, PRUint32 *aUVSTableOffset,
704 : bool *aSymbolEncoding);
705 :
706 : static nsresult
707 : ReadCMAP(const PRUint8 *aBuf, PRUint32 aBufLength,
708 : gfxSparseBitSet& aCharacterMap,
709 : PRUint32& aUVSOffset,
710 : bool& aUnicodeFont, bool& aSymbolFont);
711 :
712 : static PRUint32
713 : MapCharToGlyphFormat4(const PRUint8 *aBuf, PRUnichar aCh);
714 :
715 : static PRUint32
716 : MapCharToGlyphFormat12(const PRUint8 *aBuf, PRUint32 aCh);
717 :
718 : static PRUint16
719 : MapUVSToGlyphFormat14(const PRUint8 *aBuf, PRUint32 aCh, PRUint32 aVS);
720 :
721 : static PRUint32
722 : MapCharToGlyph(const PRUint8 *aBuf, PRUint32 aBufLength, PRUint32 aCh);
723 :
724 : #ifdef XP_WIN
725 :
726 : // given a TrueType/OpenType data file, produce a EOT-format header
727 : // for use with Windows T2Embed API AddFontResource type API's
728 : // effectively hide existing fonts with matching names aHeaderLen is
729 : // the size of the header buffer on input, the actual size of the
730 : // EOT header on output
731 : static nsresult
732 : MakeEOTHeader(const PRUint8 *aFontData, PRUint32 aFontDataLength,
733 : FallibleTArray<PRUint8> *aHeader, FontDataOverlay *aOverlay);
734 :
735 : // determine whether a font (which has already passed ValidateSFNTHeaders)
736 : // is CFF format rather than TrueType
737 : static bool
738 : IsCffFont(const PRUint8* aFontData, bool& hasVertical);
739 :
740 : #endif
741 :
742 : // determine the format of font data
743 : static gfxUserFontType
744 : DetermineFontDataType(const PRUint8 *aFontData, PRUint32 aFontDataLength);
745 :
746 : // checks for valid SFNT table structure, returns true if valid
747 : // does *not* guarantee that all font data is valid, though it does
748 : // check that key tables such as 'name' are present and readable.
749 : // XXX to be removed if/when we eliminate the option to disable OTS,
750 : // which does more thorough validation.
751 : static bool
752 : ValidateSFNTHeaders(const PRUint8 *aFontData, PRUint32 aFontDataLength);
753 :
754 : // Read the fullname from the sfnt data (used to save the original name
755 : // prior to renaming the font for installation).
756 : // This is called with sfnt data that has already been validated,
757 : // so it should always succeed in finding the name table.
758 : static nsresult
759 : GetFullNameFromSFNT(const PRUint8* aFontData, PRUint32 aLength,
760 : nsAString& aFullName);
761 :
762 : // helper to get fullname from name table
763 : static nsresult
764 : GetFullNameFromTable(FallibleTArray<PRUint8>& aNameTable,
765 : nsAString& aFullName);
766 :
767 : // create a new name table and build a new font with that name table
768 : // appended on the end, returns true on success
769 : static nsresult
770 : RenameFont(const nsAString& aName, const PRUint8 *aFontData,
771 : PRUint32 aFontDataLength, FallibleTArray<PRUint8> *aNewFont);
772 :
773 : // read all names matching aNameID, returning in aNames array
774 : static nsresult
775 : ReadNames(FallibleTArray<PRUint8>& aNameTable, PRUint32 aNameID,
776 : PRInt32 aPlatformID, nsTArray<nsString>& aNames);
777 :
778 : // reads English or first name matching aNameID, returning in aName
779 : // platform based on OS
780 : static nsresult
781 : ReadCanonicalName(FallibleTArray<PRUint8>& aNameTable, PRUint32 aNameID,
782 : nsString& aName);
783 :
784 : // convert a name from the raw name table data into an nsString,
785 : // provided we know how; return true if successful, or false
786 : // if we can't handle the encoding
787 : static bool
788 : DecodeFontName(const PRUint8 *aBuf, PRInt32 aLength,
789 : PRUint32 aPlatformCode, PRUint32 aScriptCode,
790 : PRUint32 aLangCode, nsAString& dest);
791 :
792 0 : static inline bool IsJoinCauser(PRUint32 ch) {
793 0 : return (ch == 0x200D);
794 : }
795 :
796 0 : static inline bool IsJoinControl(PRUint32 ch) {
797 0 : return (ch == 0x200C || ch == 0x200D);
798 : }
799 :
800 : enum {
801 : kUnicodeVS1 = 0xFE00,
802 : kUnicodeVS16 = 0xFE0F,
803 : kUnicodeVS17 = 0xE0100,
804 : kUnicodeVS256 = 0xE01EF
805 : };
806 :
807 0 : static inline bool IsVarSelector(PRUint32 ch) {
808 : return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
809 0 : (ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
810 : }
811 :
812 : static inline bool IsInvalid(PRUint32 ch) {
813 : return (ch == 0xFFFD);
814 : }
815 :
816 : // Font code may want to know if there is the potential for bidi behavior
817 : // to be triggered by any of the characters in a text run; this can be
818 : // used to test that possibility.
819 : enum {
820 : kUnicodeBidiScriptsStart = 0x0590,
821 : kUnicodeBidiScriptsEnd = 0x08FF,
822 : kUnicodeBidiPresentationStart = 0xFB1D,
823 : kUnicodeBidiPresentationEnd = 0xFEFC,
824 : kUnicodeFirstHighSurrogateBlock = 0xD800,
825 : kUnicodeRLM = 0x200F,
826 : kUnicodeRLE = 0x202B,
827 : kUnicodeRLO = 0x202E
828 : };
829 :
830 : static inline bool PotentialRTLChar(PRUnichar aCh) {
831 : if (aCh >= kUnicodeBidiScriptsStart && aCh <= kUnicodeBidiScriptsEnd)
832 : // bidi scripts Hebrew, Arabic, Syriac, Thaana, N'Ko are all encoded together
833 : return true;
834 :
835 : if (aCh == kUnicodeRLM || aCh == kUnicodeRLE || aCh == kUnicodeRLO)
836 : // directional controls that trigger bidi layout
837 : return true;
838 :
839 : if (aCh >= kUnicodeBidiPresentationStart &&
840 : aCh <= kUnicodeBidiPresentationEnd)
841 : // presentation forms of Arabic and Hebrew letters
842 : return true;
843 :
844 : if ((aCh & 0xFF00) == kUnicodeFirstHighSurrogateBlock)
845 : // surrogate that could be part of a bidi supplementary char
846 : // (Cypriot, Aramaic, Phoenecian, etc)
847 : return true;
848 :
849 : // otherwise we know this char cannot trigger bidi reordering
850 : return false;
851 : }
852 :
853 : static PRUint8 CharRangeBit(PRUint32 ch);
854 :
855 : // for a given font list pref name, set up a list of font names
856 : static void GetPrefsFontList(const char *aPrefName,
857 : nsTArray<nsString>& aFontList);
858 :
859 : // generate a unique font name
860 : static nsresult MakeUniqueUserFontName(nsAString& aName);
861 :
862 : protected:
863 : static nsresult
864 : ReadNames(FallibleTArray<PRUint8>& aNameTable, PRUint32 aNameID,
865 : PRInt32 aLangID, PRInt32 aPlatformID, nsTArray<nsString>& aNames);
866 :
867 : // convert opentype name-table platform/encoding/language values to a charset name
868 : // we can use to convert the name data to unicode, or "" if data is UTF16BE
869 : static const char*
870 : GetCharsetForFontName(PRUint16 aPlatform, PRUint16 aScript, PRUint16 aLanguage);
871 :
872 : struct MacFontNameCharsetMapping {
873 : PRUint16 mEncoding;
874 : PRUint16 mLanguage;
875 : const char *mCharsetName;
876 :
877 0 : bool operator<(const MacFontNameCharsetMapping& rhs) const {
878 : return (mEncoding < rhs.mEncoding) ||
879 0 : ((mEncoding == rhs.mEncoding) && (mLanguage < rhs.mLanguage));
880 : }
881 : };
882 : static const MacFontNameCharsetMapping gMacFontNameCharsets[];
883 : static const char* gISOFontNameCharsets[];
884 : static const char* gMSFontNameCharsets[];
885 : };
886 :
887 : // helper class for loading in font info spaced out at regular intervals
888 :
889 : class gfxFontInfoLoader {
890 : public:
891 :
892 : // state transitions:
893 : // initial ---StartLoader with delay---> timer on delay
894 : // initial ---StartLoader without delay---> timer on interval
895 : // timer on delay ---LoaderTimerFire---> timer on interval
896 : // timer on delay ---CancelLoader---> timer off
897 : // timer on interval ---CancelLoader---> timer off
898 : // timer off ---StartLoader with delay---> timer on delay
899 : // timer off ---StartLoader without delay---> timer on interval
900 : typedef enum {
901 : stateInitial,
902 : stateTimerOnDelay,
903 : stateTimerOnInterval,
904 : stateTimerOff
905 : } TimerState;
906 :
907 0 : gfxFontInfoLoader() :
908 0 : mInterval(0), mState(stateInitial)
909 : {
910 0 : }
911 :
912 0 : virtual ~gfxFontInfoLoader() {}
913 :
914 : // start timer with an initial delay, then call Run method at regular intervals
915 : void StartLoader(PRUint32 aDelay, PRUint32 aInterval) {
916 : mInterval = aInterval;
917 :
918 : // sanity check
919 : if (mState != stateInitial && mState != stateTimerOff)
920 : CancelLoader();
921 :
922 : // set up timer
923 : if (!mTimer) {
924 : mTimer = do_CreateInstance("@mozilla.org/timer;1");
925 : if (!mTimer) {
926 : NS_WARNING("Failure to create font info loader timer");
927 : return;
928 : }
929 : }
930 :
931 : // need an initial delay?
932 : PRUint32 timerInterval;
933 :
934 : if (aDelay) {
935 : mState = stateTimerOnDelay;
936 : timerInterval = aDelay;
937 : } else {
938 : mState = stateTimerOnInterval;
939 : timerInterval = mInterval;
940 : }
941 :
942 : InitLoader();
943 :
944 : // start timer
945 : mTimer->InitWithFuncCallback(LoaderTimerCallback, this, timerInterval,
946 : nsITimer::TYPE_REPEATING_SLACK);
947 : }
948 :
949 : // cancel the timer and cleanup
950 0 : void CancelLoader() {
951 0 : if (mState == stateInitial)
952 0 : return;
953 0 : mState = stateTimerOff;
954 0 : if (mTimer) {
955 0 : mTimer->Cancel();
956 : }
957 0 : FinishLoader();
958 : }
959 :
960 : protected:
961 :
962 : // Init - initialization at start time after initial delay
963 : virtual void InitLoader() = 0;
964 :
965 : // Run - called at intervals, return true to indicate done
966 : virtual bool RunLoader() = 0;
967 :
968 : // Finish - cleanup after done
969 : virtual void FinishLoader() = 0;
970 :
971 : static void LoaderTimerCallback(nsITimer *aTimer, void *aThis) {
972 : gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
973 : loader->LoaderTimerFire();
974 : }
975 :
976 : // start the timer, interval callbacks
977 : void LoaderTimerFire() {
978 : if (mState == stateTimerOnDelay) {
979 : mState = stateTimerOnInterval;
980 : mTimer->SetDelay(mInterval);
981 : }
982 :
983 : bool done = RunLoader();
984 : if (done) {
985 : CancelLoader();
986 : }
987 : }
988 :
989 : nsCOMPtr<nsITimer> mTimer;
990 : PRUint32 mInterval;
991 : TimerState mState;
992 : };
993 :
994 : #endif /* GFX_FONT_UTILS_H */
|