Bumping manifests a=b2g-bump
[gecko.git] / gfx / thebes / gfxFontUtils.h
bloba19ca0457ca45c4fafcea36192ad2bb3f7ffbb3c
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef GFX_FONT_UTILS_H
7 #define GFX_FONT_UTILS_H
9 #include "gfxPlatform.h"
10 #include "nsComponentManagerUtils.h"
11 #include "nsTArray.h"
12 #include "nsAutoPtr.h"
13 #include "mozilla/Likely.h"
14 #include "mozilla/Endian.h"
15 #include "mozilla/MemoryReporting.h"
17 #include "zlib.h"
18 #include <algorithm>
20 /* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
21 #ifdef __MINGW32__
22 #undef min
23 #undef max
24 #endif
26 typedef struct hb_blob_t hb_blob_t;
28 class gfxSparseBitSet {
29 private:
30 enum { BLOCK_SIZE = 32 }; // ==> 256 codepoints per block
31 enum { BLOCK_SIZE_BITS = BLOCK_SIZE * 8 };
32 enum { BLOCK_INDEX_SHIFT = 8 };
34 struct Block {
35 Block(const Block& aBlock) { memcpy(mBits, aBlock.mBits, sizeof(mBits)); }
36 explicit Block(unsigned char memsetValue = 0) { memset(mBits, memsetValue, BLOCK_SIZE); }
37 uint8_t mBits[BLOCK_SIZE];
40 public:
41 gfxSparseBitSet() { }
42 gfxSparseBitSet(const gfxSparseBitSet& aBitset) {
43 uint32_t len = aBitset.mBlocks.Length();
44 mBlocks.AppendElements(len);
45 for (uint32_t i = 0; i < len; ++i) {
46 Block *block = aBitset.mBlocks[i];
47 if (block)
48 mBlocks[i] = new Block(*block);
52 bool Equals(const gfxSparseBitSet *aOther) const {
53 if (mBlocks.Length() != aOther->mBlocks.Length()) {
54 return false;
56 size_t n = mBlocks.Length();
57 for (size_t i = 0; i < n; ++i) {
58 const Block *b1 = mBlocks[i];
59 const Block *b2 = aOther->mBlocks[i];
60 if (!b1 != !b2) {
61 return false;
63 if (!b1) {
64 continue;
66 if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) {
67 return false;
70 return true;
73 bool test(uint32_t aIndex) const {
74 NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
75 uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
76 if (blockIndex >= mBlocks.Length())
77 return false;
78 Block *block = mBlocks[blockIndex];
79 if (!block)
80 return false;
81 return ((block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0;
84 #if PR_LOGGING
85 // dump out contents of bitmap
86 void Dump(const char* aPrefix, eGfxLog aWhichLog) const;
87 #endif
89 bool TestRange(uint32_t aStart, uint32_t aEnd) {
90 uint32_t startBlock, endBlock, blockLen;
92 // start point is beyond the end of the block array? return false immediately
93 startBlock = aStart >> BLOCK_INDEX_SHIFT;
94 blockLen = mBlocks.Length();
95 if (startBlock >= blockLen) return false;
97 // check for blocks in range, if none, return false
98 uint32_t blockIndex;
99 bool hasBlocksInRange = false;
101 endBlock = aEnd >> BLOCK_INDEX_SHIFT;
102 blockIndex = startBlock;
103 for (blockIndex = startBlock; blockIndex <= endBlock; blockIndex++) {
104 if (blockIndex < blockLen && mBlocks[blockIndex])
105 hasBlocksInRange = true;
107 if (!hasBlocksInRange) return false;
109 Block *block;
110 uint32_t i, start, end;
112 // first block, check bits
113 if ((block = mBlocks[startBlock])) {
114 start = aStart;
115 end = std::min(aEnd, ((startBlock+1) << BLOCK_INDEX_SHIFT) - 1);
116 for (i = start; i <= end; i++) {
117 if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7)))
118 return true;
121 if (endBlock == startBlock) return false;
123 // [2..n-1] blocks check bytes
124 for (blockIndex = startBlock + 1; blockIndex < endBlock; blockIndex++) {
125 uint32_t index;
127 if (blockIndex >= blockLen || !(block = mBlocks[blockIndex])) continue;
128 for (index = 0; index < BLOCK_SIZE; index++) {
129 if (block->mBits[index])
130 return true;
134 // last block, check bits
135 if (endBlock < blockLen && (block = mBlocks[endBlock])) {
136 start = endBlock << BLOCK_INDEX_SHIFT;
137 end = aEnd;
138 for (i = start; i <= end; i++) {
139 if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7)))
140 return true;
144 return false;
147 void set(uint32_t aIndex) {
148 uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
149 if (blockIndex >= mBlocks.Length()) {
150 nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
151 if (MOZ_UNLIKELY(!blocks)) // OOM
152 return;
154 Block *block = mBlocks[blockIndex];
155 if (!block) {
156 block = new Block;
157 mBlocks[blockIndex] = block;
159 block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
162 void set(uint32_t aIndex, bool aValue) {
163 if (aValue)
164 set(aIndex);
165 else
166 clear(aIndex);
169 void SetRange(uint32_t aStart, uint32_t aEnd) {
170 const uint32_t startIndex = aStart/BLOCK_SIZE_BITS;
171 const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS;
173 if (endIndex >= mBlocks.Length()) {
174 uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length();
175 nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks);
176 if (MOZ_UNLIKELY(!blocks)) // OOM
177 return;
180 for (uint32_t i = startIndex; i <= endIndex; ++i) {
181 const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS;
182 const uint32_t blockLastBit = blockFirstBit + BLOCK_SIZE_BITS - 1;
184 Block *block = mBlocks[i];
185 if (!block) {
186 bool fullBlock = false;
187 if (aStart <= blockFirstBit && aEnd >= blockLastBit)
188 fullBlock = true;
190 block = new Block(fullBlock ? 0xFF : 0);
191 mBlocks[i] = block;
193 if (fullBlock)
194 continue;
197 const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
198 const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
200 for (uint32_t bit = start; bit <= end; ++bit) {
201 block->mBits[bit>>3] |= 1 << (bit & 0x7);
206 void clear(uint32_t aIndex) {
207 uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
208 if (blockIndex >= mBlocks.Length()) {
209 nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
210 if (MOZ_UNLIKELY(!blocks)) // OOM
211 return;
213 Block *block = mBlocks[blockIndex];
214 if (!block) {
215 return;
217 block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] &= ~(1 << (aIndex & 0x7));
220 void ClearRange(uint32_t aStart, uint32_t aEnd) {
221 const uint32_t startIndex = aStart/BLOCK_SIZE_BITS;
222 const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS;
224 if (endIndex >= mBlocks.Length()) {
225 uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length();
226 nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks);
227 if (MOZ_UNLIKELY(!blocks)) // OOM
228 return;
231 for (uint32_t i = startIndex; i <= endIndex; ++i) {
232 const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS;
234 Block *block = mBlocks[i];
235 if (!block) {
236 // any nonexistent block is implicitly all clear,
237 // so there's no need to even create it
238 continue;
241 const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
242 const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
244 for (uint32_t bit = start; bit <= end; ++bit) {
245 block->mBits[bit>>3] &= ~(1 << (bit & 0x7));
250 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
251 size_t total = mBlocks.SizeOfExcludingThis(aMallocSizeOf);
252 for (uint32_t i = 0; i < mBlocks.Length(); i++) {
253 if (mBlocks[i]) {
254 total += aMallocSizeOf(mBlocks[i]);
257 return total;
260 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
261 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
264 // clear out all blocks in the array
265 void reset() {
266 uint32_t i;
267 for (i = 0; i < mBlocks.Length(); i++)
268 mBlocks[i] = nullptr;
271 // set this bitset to the union of its current contents and another
272 void Union(const gfxSparseBitSet& aBitset) {
273 // ensure mBlocks is large enough
274 uint32_t blockCount = aBitset.mBlocks.Length();
275 if (blockCount > mBlocks.Length()) {
276 uint32_t needed = blockCount - mBlocks.Length();
277 nsAutoPtr<Block> *blocks = mBlocks.AppendElements(needed);
278 if (MOZ_UNLIKELY(!blocks)) { // OOM
279 return;
282 // for each block that may be present in aBitset...
283 for (uint32_t i = 0; i < blockCount; ++i) {
284 // if it is missing (implicitly empty), just skip
285 if (!aBitset.mBlocks[i]) {
286 continue;
288 // if the block is missing in this set, just copy the other
289 if (!mBlocks[i]) {
290 mBlocks[i] = new Block(*aBitset.mBlocks[i]);
291 continue;
293 // else set existing block to the union of both
294 uint32_t *dst = reinterpret_cast<uint32_t*>(mBlocks[i]->mBits);
295 const uint32_t *src =
296 reinterpret_cast<const uint32_t*>(aBitset.mBlocks[i]->mBits);
297 for (uint32_t j = 0; j < BLOCK_SIZE / 4; ++j) {
298 dst[j] |= src[j];
303 void Compact() {
304 mBlocks.Compact();
307 uint32_t GetChecksum() const {
308 uint32_t check = adler32(0, Z_NULL, 0);
309 for (uint32_t i = 0; i < mBlocks.Length(); i++) {
310 if (mBlocks[i]) {
311 const Block *block = mBlocks[i];
312 check = adler32(check, (uint8_t*) (&i), 4);
313 check = adler32(check, (uint8_t*) block, sizeof(Block));
316 return check;
319 private:
320 nsTArray< nsAutoPtr<Block> > mBlocks;
323 #define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
325 namespace mozilla {
327 // Byte-swapping types and name table structure definitions moved from
328 // gfxFontUtils.cpp to .h file so that gfxFont.cpp can also refer to them
329 #pragma pack(1)
331 struct AutoSwap_PRUint16 {
332 #ifdef __SUNPRO_CC
333 AutoSwap_PRUint16& operator = (const uint16_t aValue)
335 this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
336 return *this;
338 #else
339 MOZ_IMPLICIT AutoSwap_PRUint16(uint16_t aValue)
341 value = mozilla::NativeEndian::swapToBigEndian(aValue);
343 #endif
344 operator uint16_t() const
346 return mozilla::NativeEndian::swapFromBigEndian(value);
349 operator uint32_t() const
351 return mozilla::NativeEndian::swapFromBigEndian(value);
354 operator uint64_t() const
356 return mozilla::NativeEndian::swapFromBigEndian(value);
359 private:
360 uint16_t value;
363 struct AutoSwap_PRInt16 {
364 #ifdef __SUNPRO_CC
365 AutoSwap_PRInt16& operator = (const int16_t aValue)
367 this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
368 return *this;
370 #else
371 MOZ_IMPLICIT AutoSwap_PRInt16(int16_t aValue)
373 value = mozilla::NativeEndian::swapToBigEndian(aValue);
375 #endif
376 operator int16_t() const
378 return mozilla::NativeEndian::swapFromBigEndian(value);
381 operator uint32_t() const
383 return mozilla::NativeEndian::swapFromBigEndian(value);
386 private:
387 int16_t value;
390 struct AutoSwap_PRUint32 {
391 #ifdef __SUNPRO_CC
392 AutoSwap_PRUint32& operator = (const uint32_t aValue)
394 this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
395 return *this;
397 #else
398 MOZ_IMPLICIT AutoSwap_PRUint32(uint32_t aValue)
400 value = mozilla::NativeEndian::swapToBigEndian(aValue);
402 #endif
403 operator uint32_t() const
405 return mozilla::NativeEndian::swapFromBigEndian(value);
408 private:
409 uint32_t value;
412 struct AutoSwap_PRInt32 {
413 #ifdef __SUNPRO_CC
414 AutoSwap_PRInt32& operator = (const int32_t aValue)
416 this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
417 return *this;
419 #else
420 MOZ_IMPLICIT AutoSwap_PRInt32(int32_t aValue)
422 value = mozilla::NativeEndian::swapToBigEndian(aValue);
424 #endif
425 operator int32_t() const
427 return mozilla::NativeEndian::swapFromBigEndian(value);
430 private:
431 int32_t value;
434 struct AutoSwap_PRUint64 {
435 #ifdef __SUNPRO_CC
436 AutoSwap_PRUint64& operator = (const uint64_t aValue)
438 this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
439 return *this;
441 #else
442 MOZ_IMPLICIT AutoSwap_PRUint64(uint64_t aValue)
444 value = mozilla::NativeEndian::swapToBigEndian(aValue);
446 #endif
447 operator uint64_t() const
449 return mozilla::NativeEndian::swapFromBigEndian(value);
452 private:
453 uint64_t value;
456 struct AutoSwap_PRUint24 {
457 operator uint32_t() const { return value[0] << 16 | value[1] << 8 | value[2]; }
458 private:
459 AutoSwap_PRUint24() { }
460 uint8_t value[3];
463 struct SFNTHeader {
464 AutoSwap_PRUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0.
465 AutoSwap_PRUint16 numTables; // Number of tables.
466 AutoSwap_PRUint16 searchRange; // (Maximum power of 2 <= numTables) x 16.
467 AutoSwap_PRUint16 entrySelector; // Log2(maximum power of 2 <= numTables).
468 AutoSwap_PRUint16 rangeShift; // NumTables x 16-searchRange.
471 struct TableDirEntry {
472 AutoSwap_PRUint32 tag; // 4 -byte identifier.
473 AutoSwap_PRUint32 checkSum; // CheckSum for this table.
474 AutoSwap_PRUint32 offset; // Offset from beginning of TrueType font file.
475 AutoSwap_PRUint32 length; // Length of this table.
478 struct HeadTable {
479 enum {
480 HEAD_VERSION = 0x00010000,
481 HEAD_MAGIC_NUMBER = 0x5F0F3CF5,
482 HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA
485 AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0.
486 AutoSwap_PRUint32 fontRevision; // Set by font manufacturer.
487 AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
488 AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5.
489 AutoSwap_PRUint16 flags;
490 AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
491 AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
492 AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
493 AutoSwap_PRInt16 xMin; // For all glyph bounding boxes.
494 AutoSwap_PRInt16 yMin; // For all glyph bounding boxes.
495 AutoSwap_PRInt16 xMax; // For all glyph bounding boxes.
496 AutoSwap_PRInt16 yMax; // For all glyph bounding boxes.
497 AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1);
498 AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels.
499 AutoSwap_PRInt16 fontDirectionHint;
500 AutoSwap_PRInt16 indexToLocFormat;
501 AutoSwap_PRInt16 glyphDataFormat;
504 struct OS2Table {
505 AutoSwap_PRUint16 version; // 0004 = OpenType 1.5
506 AutoSwap_PRInt16 xAvgCharWidth;
507 AutoSwap_PRUint16 usWeightClass;
508 AutoSwap_PRUint16 usWidthClass;
509 AutoSwap_PRUint16 fsType;
510 AutoSwap_PRInt16 ySubscriptXSize;
511 AutoSwap_PRInt16 ySubscriptYSize;
512 AutoSwap_PRInt16 ySubscriptXOffset;
513 AutoSwap_PRInt16 ySubscriptYOffset;
514 AutoSwap_PRInt16 ySuperscriptXSize;
515 AutoSwap_PRInt16 ySuperscriptYSize;
516 AutoSwap_PRInt16 ySuperscriptXOffset;
517 AutoSwap_PRInt16 ySuperscriptYOffset;
518 AutoSwap_PRInt16 yStrikeoutSize;
519 AutoSwap_PRInt16 yStrikeoutPosition;
520 AutoSwap_PRInt16 sFamilyClass;
521 uint8_t panose[10];
522 AutoSwap_PRUint32 unicodeRange1;
523 AutoSwap_PRUint32 unicodeRange2;
524 AutoSwap_PRUint32 unicodeRange3;
525 AutoSwap_PRUint32 unicodeRange4;
526 uint8_t achVendID[4];
527 AutoSwap_PRUint16 fsSelection;
528 AutoSwap_PRUint16 usFirstCharIndex;
529 AutoSwap_PRUint16 usLastCharIndex;
530 AutoSwap_PRInt16 sTypoAscender;
531 AutoSwap_PRInt16 sTypoDescender;
532 AutoSwap_PRInt16 sTypoLineGap;
533 AutoSwap_PRUint16 usWinAscent;
534 AutoSwap_PRUint16 usWinDescent;
535 AutoSwap_PRUint32 codePageRange1;
536 AutoSwap_PRUint32 codePageRange2;
537 AutoSwap_PRInt16 sxHeight;
538 AutoSwap_PRInt16 sCapHeight;
539 AutoSwap_PRUint16 usDefaultChar;
540 AutoSwap_PRUint16 usBreakChar;
541 AutoSwap_PRUint16 usMaxContext;
544 struct PostTable {
545 AutoSwap_PRUint32 version;
546 AutoSwap_PRInt32 italicAngle;
547 AutoSwap_PRInt16 underlinePosition;
548 AutoSwap_PRUint16 underlineThickness;
549 AutoSwap_PRUint32 isFixedPitch;
550 AutoSwap_PRUint32 minMemType42;
551 AutoSwap_PRUint32 maxMemType42;
552 AutoSwap_PRUint32 minMemType1;
553 AutoSwap_PRUint32 maxMemType1;
556 struct HheaTable {
557 AutoSwap_PRUint32 version;
558 AutoSwap_PRInt16 ascender;
559 AutoSwap_PRInt16 descender;
560 AutoSwap_PRInt16 lineGap;
561 AutoSwap_PRUint16 advanceWidthMax;
562 AutoSwap_PRInt16 minLeftSideBearing;
563 AutoSwap_PRInt16 minRightSideBearing;
564 AutoSwap_PRInt16 xMaxExtent;
565 AutoSwap_PRInt16 caretSlopeRise;
566 AutoSwap_PRInt16 caretSlopeRun;
567 AutoSwap_PRInt16 caretOffset;
568 AutoSwap_PRInt16 reserved1;
569 AutoSwap_PRInt16 reserved2;
570 AutoSwap_PRInt16 reserved3;
571 AutoSwap_PRInt16 reserved4;
572 AutoSwap_PRInt16 metricDataFormat;
573 AutoSwap_PRUint16 numOfLongHorMetrics;
576 struct MaxpTableHeader {
577 AutoSwap_PRUint32 version; // CFF: 0x00005000; TrueType: 0x00010000
578 AutoSwap_PRUint16 numGlyphs;
579 // truetype version has additional fields that we don't currently use
582 // old 'kern' table, supported on Windows
583 // see http://www.microsoft.com/typography/otspec/kern.htm
584 struct KernTableVersion0 {
585 AutoSwap_PRUint16 version; // 0x0000
586 AutoSwap_PRUint16 nTables;
589 struct KernTableSubtableHeaderVersion0 {
590 AutoSwap_PRUint16 version;
591 AutoSwap_PRUint16 length;
592 AutoSwap_PRUint16 coverage;
595 // newer Mac-only 'kern' table, ignored by Windows
596 // see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6kern.html
597 struct KernTableVersion1 {
598 AutoSwap_PRUint32 version; // 0x00010000
599 AutoSwap_PRUint32 nTables;
602 struct KernTableSubtableHeaderVersion1 {
603 AutoSwap_PRUint32 length;
604 AutoSwap_PRUint16 coverage;
605 AutoSwap_PRUint16 tupleIndex;
608 struct COLRHeader {
609 AutoSwap_PRUint16 version;
610 AutoSwap_PRUint16 numBaseGlyphRecord;
611 AutoSwap_PRUint32 offsetBaseGlyphRecord;
612 AutoSwap_PRUint32 offsetLayerRecord;
613 AutoSwap_PRUint16 numLayerRecords;
616 struct CPALHeaderVersion0 {
617 AutoSwap_PRUint16 version;
618 AutoSwap_PRUint16 numPaletteEntries;
619 AutoSwap_PRUint16 numPalettes;
620 AutoSwap_PRUint16 numColorRecords;
621 AutoSwap_PRUint32 offsetFirstColorRecord;
624 #pragma pack()
626 // Return just the highest bit of the given value, i.e., the highest
627 // power of 2 that is <= value, or zero if the input value is zero.
628 inline uint32_t
629 FindHighestBit(uint32_t value)
631 // propagate highest bit into all lower bits of the value
632 value |= (value >> 1);
633 value |= (value >> 2);
634 value |= (value >> 4);
635 value |= (value >> 8);
636 value |= (value >> 16);
637 // isolate the leftmost bit
638 return (value & ~(value >> 1));
641 } // namespace mozilla
643 // used for overlaying name changes without touching original font data
644 struct FontDataOverlay {
645 // overlaySrc != 0 ==> use overlay
646 uint32_t overlaySrc; // src offset from start of font data
647 uint32_t overlaySrcLen; // src length
648 uint32_t overlayDest; // dest offset from start of font data
651 enum gfxUserFontType {
652 GFX_USERFONT_UNKNOWN = 0,
653 GFX_USERFONT_OPENTYPE = 1,
654 GFX_USERFONT_SVG = 2,
655 GFX_USERFONT_WOFF = 3
658 extern const uint8_t sCJKCompatSVSTable[];
660 class gfxFontUtils {
662 public:
663 // these are public because gfxFont.cpp also looks into the name table
664 enum {
665 NAME_ID_FAMILY = 1,
666 NAME_ID_STYLE = 2,
667 NAME_ID_UNIQUE = 3,
668 NAME_ID_FULL = 4,
669 NAME_ID_VERSION = 5,
670 NAME_ID_POSTSCRIPT = 6,
671 NAME_ID_PREFERRED_FAMILY = 16,
672 NAME_ID_PREFERRED_STYLE = 17,
674 PLATFORM_ALL = -1,
675 PLATFORM_ID_UNICODE = 0, // Mac OS uses this typically
676 PLATFORM_ID_MAC = 1,
677 PLATFORM_ID_ISO = 2,
678 PLATFORM_ID_MICROSOFT = 3,
680 ENCODING_ID_MAC_ROMAN = 0, // traditional Mac OS script manager encodings
681 ENCODING_ID_MAC_JAPANESE = 1, // (there are others defined, but some were never
682 ENCODING_ID_MAC_TRAD_CHINESE = 2, // implemented by Apple, and I have never seen them
683 ENCODING_ID_MAC_KOREAN = 3, // used in font names)
684 ENCODING_ID_MAC_ARABIC = 4,
685 ENCODING_ID_MAC_HEBREW = 5,
686 ENCODING_ID_MAC_GREEK = 6,
687 ENCODING_ID_MAC_CYRILLIC = 7,
688 ENCODING_ID_MAC_DEVANAGARI = 9,
689 ENCODING_ID_MAC_GURMUKHI = 10,
690 ENCODING_ID_MAC_GUJARATI = 11,
691 ENCODING_ID_MAC_SIMP_CHINESE = 25,
693 ENCODING_ID_MICROSOFT_SYMBOL = 0, // Microsoft platform encoding IDs
694 ENCODING_ID_MICROSOFT_UNICODEBMP = 1,
695 ENCODING_ID_MICROSOFT_SHIFTJIS = 2,
696 ENCODING_ID_MICROSOFT_PRC = 3,
697 ENCODING_ID_MICROSOFT_BIG5 = 4,
698 ENCODING_ID_MICROSOFT_WANSUNG = 5,
699 ENCODING_ID_MICROSOFT_JOHAB = 6,
700 ENCODING_ID_MICROSOFT_UNICODEFULL = 10,
702 LANG_ALL = -1,
703 LANG_ID_MAC_ENGLISH = 0, // many others are defined, but most don't affect
704 LANG_ID_MAC_HEBREW = 10, // the charset; should check all the central/eastern
705 LANG_ID_MAC_JAPANESE = 11, // european codes, though
706 LANG_ID_MAC_ARABIC = 12,
707 LANG_ID_MAC_ICELANDIC = 15,
708 LANG_ID_MAC_TURKISH = 17,
709 LANG_ID_MAC_TRAD_CHINESE = 19,
710 LANG_ID_MAC_URDU = 20,
711 LANG_ID_MAC_KOREAN = 23,
712 LANG_ID_MAC_POLISH = 25,
713 LANG_ID_MAC_FARSI = 31,
714 LANG_ID_MAC_SIMP_CHINESE = 33,
715 LANG_ID_MAC_ROMANIAN = 37,
716 LANG_ID_MAC_CZECH = 38,
717 LANG_ID_MAC_SLOVAK = 39,
719 LANG_ID_MICROSOFT_EN_US = 0x0409, // with Microsoft platformID, EN US lang code
721 CMAP_MAX_CODEPOINT = 0x10ffff // maximum possible Unicode codepoint
722 // contained in a cmap
725 // name table has a header, followed by name records, followed by string data
726 struct NameHeader {
727 mozilla::AutoSwap_PRUint16 format; // Format selector (=0).
728 mozilla::AutoSwap_PRUint16 count; // Number of name records.
729 mozilla::AutoSwap_PRUint16 stringOffset; // Offset to start of string storage
730 // (from start of table)
733 struct NameRecord {
734 mozilla::AutoSwap_PRUint16 platformID; // Platform ID
735 mozilla::AutoSwap_PRUint16 encodingID; // Platform-specific encoding ID
736 mozilla::AutoSwap_PRUint16 languageID; // Language ID
737 mozilla::AutoSwap_PRUint16 nameID; // Name ID.
738 mozilla::AutoSwap_PRUint16 length; // String length (in bytes).
739 mozilla::AutoSwap_PRUint16 offset; // String offset from start of storage
740 // (in bytes).
743 // for reading big-endian font data on either big or little-endian platforms
745 static inline uint16_t
746 ReadShortAt(const uint8_t *aBuf, uint32_t aIndex)
748 return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
751 static inline uint16_t
752 ReadShortAt16(const uint16_t *aBuf, uint32_t aIndex)
754 const uint8_t *buf = reinterpret_cast<const uint8_t*>(aBuf);
755 uint32_t index = aIndex << 1;
756 return (buf[index] << 8) | buf[index+1];
759 static inline uint32_t
760 ReadUint24At(const uint8_t *aBuf, uint32_t aIndex)
762 return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) |
763 (aBuf[aIndex + 2]));
766 static inline uint32_t
767 ReadLongAt(const uint8_t *aBuf, uint32_t aIndex)
769 return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
770 (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
773 static nsresult
774 ReadCMAPTableFormat12(const uint8_t *aBuf, uint32_t aLength,
775 gfxSparseBitSet& aCharacterMap);
777 static nsresult
778 ReadCMAPTableFormat4(const uint8_t *aBuf, uint32_t aLength,
779 gfxSparseBitSet& aCharacterMap);
781 static nsresult
782 ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength,
783 uint8_t*& aTable);
785 static uint32_t
786 FindPreferredSubtable(const uint8_t *aBuf, uint32_t aBufLength,
787 uint32_t *aTableOffset, uint32_t *aUVSTableOffset,
788 bool *aSymbolEncoding);
790 static nsresult
791 ReadCMAP(const uint8_t *aBuf, uint32_t aBufLength,
792 gfxSparseBitSet& aCharacterMap,
793 uint32_t& aUVSOffset,
794 bool& aUnicodeFont, bool& aSymbolFont);
796 static uint32_t
797 MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh);
799 static uint32_t
800 MapCharToGlyphFormat12(const uint8_t *aBuf, uint32_t aCh);
802 static uint16_t
803 MapUVSToGlyphFormat14(const uint8_t *aBuf, uint32_t aCh, uint32_t aVS);
805 // sCJKCompatSVSTable is a 'cmap' format 14 subtable that maps
806 // <char + var-selector> pairs to the corresponding Unicode
807 // compatibility ideograph codepoints.
808 static MOZ_ALWAYS_INLINE uint32_t
809 GetUVSFallback(uint32_t aCh, uint32_t aVS) {
810 aCh = MapUVSToGlyphFormat14(sCJKCompatSVSTable, aCh, aVS);
811 return aCh >= 0xFB00 ? aCh + (0x2F800 - 0xFB00) : aCh;
814 static uint32_t
815 MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
816 uint32_t aUnicode, uint32_t aVarSelector = 0);
818 #ifdef XP_WIN
819 // determine whether a font (which has already been sanitized, so is known
820 // to be a valid sfnt) is CFF format rather than TrueType
821 static bool
822 IsCffFont(const uint8_t* aFontData);
823 #endif
825 // determine the format of font data
826 static gfxUserFontType
827 DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontDataLength);
829 // Read the fullname from the sfnt data (used to save the original name
830 // prior to renaming the font for installation).
831 // This is called with sfnt data that has already been validated,
832 // so it should always succeed in finding the name table.
833 static nsresult
834 GetFullNameFromSFNT(const uint8_t* aFontData, uint32_t aLength,
835 nsAString& aFullName);
837 // helper to get fullname from name table, constructing from family+style
838 // if no explicit fullname is present
839 static nsresult
840 GetFullNameFromTable(hb_blob_t *aNameTable,
841 nsAString& aFullName);
843 // helper to get family name from name table
844 static nsresult
845 GetFamilyNameFromTable(hb_blob_t *aNameTable,
846 nsAString& aFamilyName);
848 // create a new name table and build a new font with that name table
849 // appended on the end, returns true on success
850 static nsresult
851 RenameFont(const nsAString& aName, const uint8_t *aFontData,
852 uint32_t aFontDataLength, FallibleTArray<uint8_t> *aNewFont);
854 // read all names matching aNameID, returning in aNames array
855 static nsresult
856 ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID,
857 int32_t aPlatformID, nsTArray<nsString>& aNames);
859 // reads English or first name matching aNameID, returning in aName
860 // platform based on OS
861 static nsresult
862 ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID,
863 nsString& aName);
865 static nsresult
866 ReadCanonicalName(const char *aNameData, uint32_t aDataLen,
867 uint32_t aNameID, nsString& aName);
869 // convert a name from the raw name table data into an nsString,
870 // provided we know how; return true if successful, or false
871 // if we can't handle the encoding
872 static bool
873 DecodeFontName(const char *aBuf, int32_t aLength,
874 uint32_t aPlatformCode, uint32_t aScriptCode,
875 uint32_t aLangCode, nsAString& dest);
877 static inline bool IsJoinCauser(uint32_t ch) {
878 return (ch == 0x200D);
881 static inline bool IsJoinControl(uint32_t ch) {
882 return (ch == 0x200C || ch == 0x200D);
885 enum {
886 kUnicodeVS1 = 0xFE00,
887 kUnicodeVS16 = 0xFE0F,
888 kUnicodeVS17 = 0xE0100,
889 kUnicodeVS256 = 0xE01EF
892 static inline bool IsVarSelector(uint32_t ch) {
893 return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
894 (ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
897 static inline bool IsInvalid(uint32_t ch) {
898 return (ch == 0xFFFD);
901 // Font code may want to know if there is the potential for bidi behavior
902 // to be triggered by any of the characters in a text run; this can be
903 // used to test that possibility.
904 enum {
905 kUnicodeBidiScriptsStart = 0x0590,
906 kUnicodeBidiScriptsEnd = 0x08FF,
907 kUnicodeBidiPresentationStart = 0xFB1D,
908 kUnicodeBidiPresentationEnd = 0xFEFC,
909 kUnicodeFirstHighSurrogateBlock = 0xD800,
910 kUnicodeRLM = 0x200F,
911 kUnicodeRLE = 0x202B,
912 kUnicodeRLO = 0x202E
915 static inline bool PotentialRTLChar(char16_t aCh) {
916 if (aCh >= kUnicodeBidiScriptsStart && aCh <= kUnicodeBidiScriptsEnd)
917 // bidi scripts Hebrew, Arabic, Syriac, Thaana, N'Ko are all encoded together
918 return true;
920 if (aCh == kUnicodeRLM || aCh == kUnicodeRLE || aCh == kUnicodeRLO)
921 // directional controls that trigger bidi layout
922 return true;
924 if (aCh >= kUnicodeBidiPresentationStart &&
925 aCh <= kUnicodeBidiPresentationEnd)
926 // presentation forms of Arabic and Hebrew letters
927 return true;
929 if ((aCh & 0xFF00) == kUnicodeFirstHighSurrogateBlock)
930 // surrogate that could be part of a bidi supplementary char
931 // (Cypriot, Aramaic, Phoenecian, etc)
932 return true;
934 // otherwise we know this char cannot trigger bidi reordering
935 return false;
938 // parse a simple list of font family names into
939 // an array of strings
940 static void ParseFontList(const nsAString& aFamilyList,
941 nsTArray<nsString>& aFontList);
943 // for a given font list pref name, append list of font names
944 static void AppendPrefsFontList(const char *aPrefName,
945 nsTArray<nsString>& aFontList);
947 // for a given font list pref name, initialize a list of font names
948 static void GetPrefsFontList(const char *aPrefName,
949 nsTArray<nsString>& aFontList);
951 // generate a unique font name
952 static nsresult MakeUniqueUserFontName(nsAString& aName);
954 // for color layer from glyph using COLR and CPAL tables
955 static bool ValidateColorGlyphs(hb_blob_t* aCOLR, hb_blob_t* aCPAL);
956 static bool GetColorGlyphLayers(hb_blob_t* aCOLR,
957 hb_blob_t* aCPAL,
958 uint32_t aGlyphId,
959 nsTArray<uint16_t> &aGlyphs,
960 nsTArray<mozilla::gfx::Color> &aColors);
962 protected:
963 static nsresult
964 ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID,
965 int32_t aLangID, int32_t aPlatformID, nsTArray<nsString>& aNames);
967 // convert opentype name-table platform/encoding/language values to a charset name
968 // we can use to convert the name data to unicode, or "" if data is UTF16BE
969 static const char*
970 GetCharsetForFontName(uint16_t aPlatform, uint16_t aScript, uint16_t aLanguage);
972 struct MacFontNameCharsetMapping {
973 uint16_t mEncoding;
974 uint16_t mLanguage;
975 const char *mCharsetName;
977 bool operator<(const MacFontNameCharsetMapping& rhs) const {
978 return (mEncoding < rhs.mEncoding) ||
979 ((mEncoding == rhs.mEncoding) && (mLanguage < rhs.mLanguage));
982 static const MacFontNameCharsetMapping gMacFontNameCharsets[];
983 static const char* gISOFontNameCharsets[];
984 static const char* gMSFontNameCharsets[];
988 #endif /* GFX_FONT_UTILS_H */