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/. */
5 
6 #ifndef GFX_FONT_UTILS_H
7 #define GFX_FONT_UTILS_H
8 
9 #include "gfxPlatform.h"
10 #include "nsComponentManagerUtils.h"
11 #include "nsTArray.h"
12 #include "mozilla/Likely.h"
13 #include "mozilla/EndianUtils.h"
14 #include "mozilla/MemoryReporting.h"
15 #include "mozilla/UniquePtr.h"
16 
17 #include "zlib.h"
18 #include <algorithm>
19 
20 /* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
21 #ifdef __MINGW32__
22 #undef min
23 #undef max
24 #endif
25 
26 typedef struct hb_blob_t hb_blob_t;
27 
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 };
33 
34     struct Block {
BlockBlock35         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];
38     };
39 
40 public:
gfxSparseBitSet()41     gfxSparseBitSet() { }
gfxSparseBitSet(const gfxSparseBitSet & aBitset)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].get();
47             if (block) {
48                 mBlocks[i] = mozilla::MakeUnique<Block>(*block);
49             }
50         }
51     }
52 
Equals(const gfxSparseBitSet * aOther)53     bool Equals(const gfxSparseBitSet *aOther) const {
54         if (mBlocks.Length() != aOther->mBlocks.Length()) {
55             return false;
56         }
57         size_t n = mBlocks.Length();
58         for (size_t i = 0; i < n; ++i) {
59             const Block *b1 = mBlocks[i].get();
60             const Block *b2 = aOther->mBlocks[i].get();
61             if (!b1 != !b2) {
62                 return false;
63             }
64             if (!b1) {
65                 continue;
66             }
67             if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) {
68                 return false;
69             }
70         }
71         return true;
72     }
73 
test(uint32_t aIndex)74     bool test(uint32_t aIndex) const {
75         NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
76         uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
77         if (blockIndex >= mBlocks.Length()) {
78             return false;
79         }
80         const Block *block = mBlocks[blockIndex].get();
81         if (!block) {
82             return false;
83         }
84         return ((block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0;
85     }
86 
87     // dump out contents of bitmap
88     void Dump(const char* aPrefix, eGfxLog aWhichLog) const;
89 
TestRange(uint32_t aStart,uint32_t aEnd)90     bool TestRange(uint32_t aStart, uint32_t aEnd) {
91         uint32_t startBlock, endBlock, blockLen;
92 
93         // start point is beyond the end of the block array? return false immediately
94         startBlock = aStart >> BLOCK_INDEX_SHIFT;
95         blockLen = mBlocks.Length();
96         if (startBlock >= blockLen) return false;
97 
98         // check for blocks in range, if none, return false
99         uint32_t blockIndex;
100         bool hasBlocksInRange = false;
101 
102         endBlock = aEnd >> BLOCK_INDEX_SHIFT;
103         for (blockIndex = startBlock; blockIndex <= endBlock; blockIndex++) {
104             if (blockIndex < blockLen && mBlocks[blockIndex]) {
105                 hasBlocksInRange = true;
106             }
107         }
108         if (!hasBlocksInRange) {
109             return false;
110         }
111 
112         Block *block;
113         uint32_t i, start, end;
114 
115         // first block, check bits
116         if ((block = mBlocks[startBlock].get())) {
117             start = aStart;
118             end = std::min(aEnd, ((startBlock+1) << BLOCK_INDEX_SHIFT) - 1);
119             for (i = start; i <= end; i++) {
120                 if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7))) {
121                     return true;
122                 }
123             }
124         }
125         if (endBlock == startBlock) {
126             return false;
127         }
128 
129         // [2..n-1] blocks check bytes
130         for (blockIndex = startBlock + 1; blockIndex < endBlock; blockIndex++) {
131             uint32_t index;
132 
133             if (blockIndex >= blockLen ||
134                 !(block = mBlocks[blockIndex].get())) {
135                 continue;
136             }
137             for (index = 0; index < BLOCK_SIZE; index++) {
138                 if (block->mBits[index]) {
139                     return true;
140                 }
141             }
142         }
143 
144         // last block, check bits
145         if (endBlock < blockLen && (block = mBlocks[endBlock].get())) {
146             start = endBlock << BLOCK_INDEX_SHIFT;
147             end = aEnd;
148             for (i = start; i <= end; i++) {
149                 if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7))) {
150                     return true;
151                 }
152             }
153         }
154 
155         return false;
156     }
157 
set(uint32_t aIndex)158     void set(uint32_t aIndex) {
159         uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
160         if (blockIndex >= mBlocks.Length()) {
161             mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
162         }
163         Block *block = mBlocks[blockIndex].get();
164         if (!block) {
165             block = new Block;
166             mBlocks[blockIndex].reset(block);
167         }
168         block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
169     }
170 
set(uint32_t aIndex,bool aValue)171     void set(uint32_t aIndex, bool aValue) {
172         if (aValue)
173             set(aIndex);
174         else
175             clear(aIndex);
176     }
177 
SetRange(uint32_t aStart,uint32_t aEnd)178     void SetRange(uint32_t aStart, uint32_t aEnd) {
179         const uint32_t startIndex = aStart/BLOCK_SIZE_BITS;
180         const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS;
181 
182         if (endIndex >= mBlocks.Length()) {
183             uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length();
184             mBlocks.AppendElements(numNewBlocks);
185         }
186 
187         for (uint32_t i = startIndex; i <= endIndex; ++i) {
188             const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS;
189             const uint32_t blockLastBit = blockFirstBit + BLOCK_SIZE_BITS - 1;
190 
191             Block *block = mBlocks[i].get();
192             if (!block) {
193                 bool fullBlock =
194                     (aStart <= blockFirstBit && aEnd >= blockLastBit);
195 
196                 block = new Block(fullBlock ? 0xFF : 0);
197                 mBlocks[i].reset(block);
198 
199                 if (fullBlock) {
200                     continue;
201                 }
202             }
203 
204             const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
205             const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
206 
207             for (uint32_t bit = start; bit <= end; ++bit) {
208                 block->mBits[bit>>3] |= 1 << (bit & 0x7);
209             }
210         }
211     }
212 
clear(uint32_t aIndex)213     void clear(uint32_t aIndex) {
214         uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
215         if (blockIndex >= mBlocks.Length()) {
216             mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
217         }
218         Block *block = mBlocks[blockIndex].get();
219         if (!block) {
220             return;
221         }
222         block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] &= ~(1 << (aIndex & 0x7));
223     }
224 
ClearRange(uint32_t aStart,uint32_t aEnd)225     void ClearRange(uint32_t aStart, uint32_t aEnd) {
226         const uint32_t startIndex = aStart/BLOCK_SIZE_BITS;
227         const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS;
228 
229         if (endIndex >= mBlocks.Length()) {
230             uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length();
231             mBlocks.AppendElements(numNewBlocks);
232         }
233 
234         for (uint32_t i = startIndex; i <= endIndex; ++i) {
235             const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS;
236 
237             Block *block = mBlocks[i].get();
238             if (!block) {
239                 // any nonexistent block is implicitly all clear,
240                 // so there's no need to even create it
241                 continue;
242             }
243 
244             const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
245             const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
246 
247             for (uint32_t bit = start; bit <= end; ++bit) {
248                 block->mBits[bit>>3] &= ~(1 << (bit & 0x7));
249             }
250         }
251     }
252 
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)253     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
254         size_t total = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
255         for (uint32_t i = 0; i < mBlocks.Length(); i++) {
256             if (mBlocks[i]) {
257                 total += aMallocSizeOf(mBlocks[i].get());
258             }
259         }
260         return total;
261     }
262 
SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)263     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
264         return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
265     }
266 
267     // clear out all blocks in the array
reset()268     void reset() {
269         uint32_t i;
270         for (i = 0; i < mBlocks.Length(); i++) {
271             mBlocks[i] = nullptr;
272         }
273     }
274 
275     // set this bitset to the union of its current contents and another
Union(const gfxSparseBitSet & aBitset)276     void Union(const gfxSparseBitSet& aBitset) {
277         // ensure mBlocks is large enough
278         uint32_t blockCount = aBitset.mBlocks.Length();
279         if (blockCount > mBlocks.Length()) {
280             uint32_t needed = blockCount - mBlocks.Length();
281             mBlocks.AppendElements(needed);
282         }
283         // for each block that may be present in aBitset...
284         for (uint32_t i = 0; i < blockCount; ++i) {
285             // if it is missing (implicitly empty), just skip
286             if (!aBitset.mBlocks[i]) {
287                 continue;
288             }
289             // if the block is missing in this set, just copy the other
290             if (!mBlocks[i]) {
291                 mBlocks[i] = mozilla::MakeUnique<Block>(*aBitset.mBlocks[i]);
292                 continue;
293             }
294             // else set existing block to the union of both
295             uint32_t *dst = reinterpret_cast<uint32_t*>(mBlocks[i]->mBits);
296             const uint32_t *src =
297                 reinterpret_cast<const uint32_t*>(aBitset.mBlocks[i]->mBits);
298             for (uint32_t j = 0; j < BLOCK_SIZE / 4; ++j) {
299                 dst[j] |= src[j];
300             }
301         }
302     }
303 
Compact()304     void Compact() {
305         mBlocks.Compact();
306     }
307 
GetChecksum()308     uint32_t GetChecksum() const {
309         uint32_t check = adler32(0, Z_NULL, 0);
310         for (uint32_t i = 0; i < mBlocks.Length(); i++) {
311             if (mBlocks[i]) {
312                 const Block *block = mBlocks[i].get();
313                 check = adler32(check, (uint8_t*) (&i), 4);
314                 check = adler32(check, (uint8_t*) block, sizeof(Block));
315             }
316         }
317         return check;
318     }
319 
320 private:
321     nsTArray<mozilla::UniquePtr<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 uint16_t aValue)
335     {
336         this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
337         return *this;
338     }
339 #else
340     MOZ_IMPLICIT AutoSwap_PRUint16(uint16_t aValue)
341     {
342         value = mozilla::NativeEndian::swapToBigEndian(aValue);
343     }
344 #endif
uint16_tAutoSwap_PRUint16345     operator uint16_t() const
346     {
347         return mozilla::NativeEndian::swapFromBigEndian(value);
348     }
349 
uint32_tAutoSwap_PRUint16350     operator uint32_t() const
351     {
352         return mozilla::NativeEndian::swapFromBigEndian(value);
353     }
354 
uint64_tAutoSwap_PRUint16355     operator uint64_t() const
356     {
357         return mozilla::NativeEndian::swapFromBigEndian(value);
358     }
359 
360 private:
361     uint16_t value;
362 };
363 
364 struct AutoSwap_PRInt16 {
365 #ifdef __SUNPRO_CC
366     AutoSwap_PRInt16& operator = (const int16_t aValue)
367     {
368         this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
369         return *this;
370     }
371 #else
372     MOZ_IMPLICIT AutoSwap_PRInt16(int16_t aValue)
373     {
374         value = mozilla::NativeEndian::swapToBigEndian(aValue);
375     }
376 #endif
int16_tAutoSwap_PRInt16377     operator int16_t() const
378     {
379         return mozilla::NativeEndian::swapFromBigEndian(value);
380     }
381 
uint32_tAutoSwap_PRInt16382     operator uint32_t() const
383     {
384         return mozilla::NativeEndian::swapFromBigEndian(value);
385     }
386 
387 private:
388     int16_t  value;
389 };
390 
391 struct AutoSwap_PRUint32 {
392 #ifdef __SUNPRO_CC
393     AutoSwap_PRUint32& operator = (const uint32_t aValue)
394     {
395         this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
396         return *this;
397     }
398 #else
399     MOZ_IMPLICIT AutoSwap_PRUint32(uint32_t aValue)
400     {
401         value = mozilla::NativeEndian::swapToBigEndian(aValue);
402     }
403 #endif
uint32_tAutoSwap_PRUint32404     operator uint32_t() const
405     {
406         return mozilla::NativeEndian::swapFromBigEndian(value);
407     }
408 
409 private:
410     uint32_t  value;
411 };
412 
413 struct AutoSwap_PRInt32 {
414 #ifdef __SUNPRO_CC
415     AutoSwap_PRInt32& operator = (const int32_t aValue)
416     {
417         this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
418         return *this;
419     }
420 #else
421     MOZ_IMPLICIT AutoSwap_PRInt32(int32_t aValue)
422     {
423         value = mozilla::NativeEndian::swapToBigEndian(aValue);
424     }
425 #endif
int32_tAutoSwap_PRInt32426     operator int32_t() const
427     {
428         return mozilla::NativeEndian::swapFromBigEndian(value);
429     }
430 
431 private:
432     int32_t  value;
433 };
434 
435 struct AutoSwap_PRUint64 {
436 #ifdef __SUNPRO_CC
437     AutoSwap_PRUint64& operator = (const uint64_t aValue)
438     {
439         this->value = mozilla::NativeEndian::swapToBigEndian(aValue);
440         return *this;
441     }
442 #else
443     MOZ_IMPLICIT AutoSwap_PRUint64(uint64_t aValue)
444     {
445         value = mozilla::NativeEndian::swapToBigEndian(aValue);
446     }
447 #endif
uint64_tAutoSwap_PRUint64448     operator uint64_t() const
449     {
450         return mozilla::NativeEndian::swapFromBigEndian(value);
451     }
452 
453 private:
454     uint64_t  value;
455 };
456 
457 struct AutoSwap_PRUint24 {
uint32_tAutoSwap_PRUint24458     operator uint32_t() const { return value[0] << 16 | value[1] << 8 | value[2]; }
459 private:
AutoSwap_PRUint24AutoSwap_PRUint24460     AutoSwap_PRUint24() { }
461     uint8_t  value[3];
462 };
463 
464 struct SFNTHeader {
465     AutoSwap_PRUint32    sfntVersion;            // Fixed, 0x00010000 for version 1.0.
466     AutoSwap_PRUint16    numTables;              // Number of tables.
467     AutoSwap_PRUint16    searchRange;            // (Maximum power of 2 <= numTables) x 16.
468     AutoSwap_PRUint16    entrySelector;          // Log2(maximum power of 2 <= numTables).
469     AutoSwap_PRUint16    rangeShift;             // NumTables x 16-searchRange.
470 };
471 
472 struct TableDirEntry {
473     AutoSwap_PRUint32    tag;                    // 4 -byte identifier.
474     AutoSwap_PRUint32    checkSum;               // CheckSum for this table.
475     AutoSwap_PRUint32    offset;                 // Offset from beginning of TrueType font file.
476     AutoSwap_PRUint32    length;                 // Length of this table.
477 };
478 
479 struct HeadTable {
480     enum {
481         HEAD_VERSION = 0x00010000,
482         HEAD_MAGIC_NUMBER = 0x5F0F3CF5,
483         HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA
484     };
485 
486     AutoSwap_PRUint32    tableVersionNumber;    // Fixed, 0x00010000 for version 1.0.
487     AutoSwap_PRUint32    fontRevision;          // Set by font manufacturer.
488     AutoSwap_PRUint32    checkSumAdjustment;    // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
489     AutoSwap_PRUint32    magicNumber;           // Set to 0x5F0F3CF5.
490     AutoSwap_PRUint16    flags;
491     AutoSwap_PRUint16    unitsPerEm;            // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
492     AutoSwap_PRUint64    created;               // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
493     AutoSwap_PRUint64    modified;              // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
494     AutoSwap_PRInt16     xMin;                  // For all glyph bounding boxes.
495     AutoSwap_PRInt16     yMin;                  // For all glyph bounding boxes.
496     AutoSwap_PRInt16     xMax;                  // For all glyph bounding boxes.
497     AutoSwap_PRInt16     yMax;                  // For all glyph bounding boxes.
498     AutoSwap_PRUint16    macStyle;              // Bit 0: Bold (if set to 1);
499     AutoSwap_PRUint16    lowestRecPPEM;         // Smallest readable size in pixels.
500     AutoSwap_PRInt16     fontDirectionHint;
501     AutoSwap_PRInt16     indexToLocFormat;
502     AutoSwap_PRInt16     glyphDataFormat;
503 };
504 
505 struct OS2Table {
506     AutoSwap_PRUint16    version;                // 0004 = OpenType 1.5
507     AutoSwap_PRInt16     xAvgCharWidth;
508     AutoSwap_PRUint16    usWeightClass;
509     AutoSwap_PRUint16    usWidthClass;
510     AutoSwap_PRUint16    fsType;
511     AutoSwap_PRInt16     ySubscriptXSize;
512     AutoSwap_PRInt16     ySubscriptYSize;
513     AutoSwap_PRInt16     ySubscriptXOffset;
514     AutoSwap_PRInt16     ySubscriptYOffset;
515     AutoSwap_PRInt16     ySuperscriptXSize;
516     AutoSwap_PRInt16     ySuperscriptYSize;
517     AutoSwap_PRInt16     ySuperscriptXOffset;
518     AutoSwap_PRInt16     ySuperscriptYOffset;
519     AutoSwap_PRInt16     yStrikeoutSize;
520     AutoSwap_PRInt16     yStrikeoutPosition;
521     AutoSwap_PRInt16     sFamilyClass;
522     uint8_t              panose[10];
523     AutoSwap_PRUint32    unicodeRange1;
524     AutoSwap_PRUint32    unicodeRange2;
525     AutoSwap_PRUint32    unicodeRange3;
526     AutoSwap_PRUint32    unicodeRange4;
527     uint8_t              achVendID[4];
528     AutoSwap_PRUint16    fsSelection;
529     AutoSwap_PRUint16    usFirstCharIndex;
530     AutoSwap_PRUint16    usLastCharIndex;
531     AutoSwap_PRInt16     sTypoAscender;
532     AutoSwap_PRInt16     sTypoDescender;
533     AutoSwap_PRInt16     sTypoLineGap;
534     AutoSwap_PRUint16    usWinAscent;
535     AutoSwap_PRUint16    usWinDescent;
536     AutoSwap_PRUint32    codePageRange1;
537     AutoSwap_PRUint32    codePageRange2;
538     AutoSwap_PRInt16     sxHeight;
539     AutoSwap_PRInt16     sCapHeight;
540     AutoSwap_PRUint16    usDefaultChar;
541     AutoSwap_PRUint16    usBreakChar;
542     AutoSwap_PRUint16    usMaxContext;
543 };
544 
545 struct PostTable {
546     AutoSwap_PRUint32    version;
547     AutoSwap_PRInt32     italicAngle;
548     AutoSwap_PRInt16     underlinePosition;
549     AutoSwap_PRUint16    underlineThickness;
550     AutoSwap_PRUint32    isFixedPitch;
551     AutoSwap_PRUint32    minMemType42;
552     AutoSwap_PRUint32    maxMemType42;
553     AutoSwap_PRUint32    minMemType1;
554     AutoSwap_PRUint32    maxMemType1;
555 };
556 
557 // This structure is used for both 'hhea' and 'vhea' tables.
558 // The field names here are those of the horizontal version; the
559 // vertical table just exchanges vertical and horizontal coordinates.
560 struct MetricsHeader {
561     AutoSwap_PRUint32    version;
562     AutoSwap_PRInt16     ascender;
563     AutoSwap_PRInt16     descender;
564     AutoSwap_PRInt16     lineGap;
565     AutoSwap_PRUint16    advanceWidthMax;
566     AutoSwap_PRInt16     minLeftSideBearing;
567     AutoSwap_PRInt16     minRightSideBearing;
568     AutoSwap_PRInt16     xMaxExtent;
569     AutoSwap_PRInt16     caretSlopeRise;
570     AutoSwap_PRInt16     caretSlopeRun;
571     AutoSwap_PRInt16     caretOffset;
572     AutoSwap_PRInt16     reserved1;
573     AutoSwap_PRInt16     reserved2;
574     AutoSwap_PRInt16     reserved3;
575     AutoSwap_PRInt16     reserved4;
576     AutoSwap_PRInt16     metricDataFormat;
577     AutoSwap_PRUint16    numOfLongMetrics;
578 };
579 
580 struct MaxpTableHeader {
581     AutoSwap_PRUint32    version; // CFF: 0x00005000; TrueType: 0x00010000
582     AutoSwap_PRUint16    numGlyphs;
583 // truetype version has additional fields that we don't currently use
584 };
585 
586 // old 'kern' table, supported on Windows
587 // see http://www.microsoft.com/typography/otspec/kern.htm
588 struct KernTableVersion0 {
589     AutoSwap_PRUint16    version; // 0x0000
590     AutoSwap_PRUint16    nTables;
591 };
592 
593 struct KernTableSubtableHeaderVersion0 {
594     AutoSwap_PRUint16    version;
595     AutoSwap_PRUint16    length;
596     AutoSwap_PRUint16    coverage;
597 };
598 
599 // newer Mac-only 'kern' table, ignored by Windows
600 // see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6kern.html
601 struct KernTableVersion1 {
602     AutoSwap_PRUint32    version; // 0x00010000
603     AutoSwap_PRUint32    nTables;
604 };
605 
606 struct KernTableSubtableHeaderVersion1 {
607     AutoSwap_PRUint32    length;
608     AutoSwap_PRUint16    coverage;
609     AutoSwap_PRUint16    tupleIndex;
610 };
611 
612 struct COLRHeader {
613     AutoSwap_PRUint16    version;
614     AutoSwap_PRUint16    numBaseGlyphRecord;
615     AutoSwap_PRUint32    offsetBaseGlyphRecord;
616     AutoSwap_PRUint32    offsetLayerRecord;
617     AutoSwap_PRUint16    numLayerRecords;
618 };
619 
620 struct CPALHeaderVersion0 {
621     AutoSwap_PRUint16    version;
622     AutoSwap_PRUint16    numPaletteEntries;
623     AutoSwap_PRUint16    numPalettes;
624     AutoSwap_PRUint16    numColorRecords;
625     AutoSwap_PRUint32    offsetFirstColorRecord;
626 };
627 
628 #pragma pack()
629 
630 // Return just the highest bit of the given value, i.e., the highest
631 // power of 2 that is <= value, or zero if the input value is zero.
632 inline uint32_t
FindHighestBit(uint32_t value)633 FindHighestBit(uint32_t value)
634 {
635     // propagate highest bit into all lower bits of the value
636     value |= (value >> 1);
637     value |= (value >> 2);
638     value |= (value >> 4);
639     value |= (value >> 8);
640     value |= (value >> 16);
641     // isolate the leftmost bit
642     return (value & ~(value >> 1));
643 }
644 
645 } // namespace mozilla
646 
647 // used for overlaying name changes without touching original font data
648 struct FontDataOverlay {
649     // overlaySrc != 0 ==> use overlay
650     uint32_t  overlaySrc;    // src offset from start of font data
651     uint32_t  overlaySrcLen; // src length
652     uint32_t  overlayDest;   // dest offset from start of font data
653 };
654 
655 enum gfxUserFontType {
656     GFX_USERFONT_UNKNOWN = 0,
657     GFX_USERFONT_OPENTYPE = 1,
658     GFX_USERFONT_SVG = 2,
659     GFX_USERFONT_WOFF = 3,
660     GFX_USERFONT_WOFF2 = 4
661 };
662 #define GFX_PREF_WOFF2_ENABLED "gfx.downloadable_fonts.woff2.enabled"
663 
664 extern const uint8_t sCJKCompatSVSTable[];
665 
666 class gfxFontUtils {
667 
668 public:
669     // these are public because gfxFont.cpp also looks into the name table
670     enum {
671         NAME_ID_FAMILY = 1,
672         NAME_ID_STYLE = 2,
673         NAME_ID_UNIQUE = 3,
674         NAME_ID_FULL = 4,
675         NAME_ID_VERSION = 5,
676         NAME_ID_POSTSCRIPT = 6,
677         NAME_ID_PREFERRED_FAMILY = 16,
678         NAME_ID_PREFERRED_STYLE = 17,
679 
680         PLATFORM_ALL = -1,
681         PLATFORM_ID_UNICODE = 0,           // Mac OS uses this typically
682         PLATFORM_ID_MAC = 1,
683         PLATFORM_ID_ISO = 2,
684         PLATFORM_ID_MICROSOFT = 3,
685 
686         ENCODING_ID_MAC_ROMAN = 0,         // traditional Mac OS script manager encodings
687         ENCODING_ID_MAC_JAPANESE = 1,      // (there are others defined, but some were never
688         ENCODING_ID_MAC_TRAD_CHINESE = 2,  // implemented by Apple, and I have never seen them
689         ENCODING_ID_MAC_KOREAN = 3,        // used in font names)
690         ENCODING_ID_MAC_ARABIC = 4,
691         ENCODING_ID_MAC_HEBREW = 5,
692         ENCODING_ID_MAC_GREEK = 6,
693         ENCODING_ID_MAC_CYRILLIC = 7,
694         ENCODING_ID_MAC_DEVANAGARI = 9,
695         ENCODING_ID_MAC_GURMUKHI = 10,
696         ENCODING_ID_MAC_GUJARATI = 11,
697         ENCODING_ID_MAC_SIMP_CHINESE = 25,
698 
699         ENCODING_ID_MICROSOFT_SYMBOL = 0,  // Microsoft platform encoding IDs
700         ENCODING_ID_MICROSOFT_UNICODEBMP = 1,
701         ENCODING_ID_MICROSOFT_SHIFTJIS = 2,
702         ENCODING_ID_MICROSOFT_PRC = 3,
703         ENCODING_ID_MICROSOFT_BIG5 = 4,
704         ENCODING_ID_MICROSOFT_WANSUNG = 5,
705         ENCODING_ID_MICROSOFT_JOHAB  = 6,
706         ENCODING_ID_MICROSOFT_UNICODEFULL = 10,
707 
708         LANG_ALL = -1,
709         LANG_ID_MAC_ENGLISH = 0,      // many others are defined, but most don't affect
710         LANG_ID_MAC_HEBREW = 10,      // the charset; should check all the central/eastern
711         LANG_ID_MAC_JAPANESE = 11,    // european codes, though
712         LANG_ID_MAC_ARABIC = 12,
713         LANG_ID_MAC_ICELANDIC = 15,
714         LANG_ID_MAC_TURKISH = 17,
715         LANG_ID_MAC_TRAD_CHINESE = 19,
716         LANG_ID_MAC_URDU = 20,
717         LANG_ID_MAC_KOREAN = 23,
718         LANG_ID_MAC_POLISH = 25,
719         LANG_ID_MAC_FARSI = 31,
720         LANG_ID_MAC_SIMP_CHINESE = 33,
721         LANG_ID_MAC_ROMANIAN = 37,
722         LANG_ID_MAC_CZECH = 38,
723         LANG_ID_MAC_SLOVAK = 39,
724 
725         LANG_ID_MICROSOFT_EN_US = 0x0409,        // with Microsoft platformID, EN US lang code
726 
727         CMAP_MAX_CODEPOINT = 0x10ffff     // maximum possible Unicode codepoint
728                                           // contained in a cmap
729     };
730 
731     // name table has a header, followed by name records, followed by string data
732     struct NameHeader {
733         mozilla::AutoSwap_PRUint16    format;       // Format selector (=0).
734         mozilla::AutoSwap_PRUint16    count;        // Number of name records.
735         mozilla::AutoSwap_PRUint16    stringOffset; // Offset to start of string storage
736                                                     // (from start of table)
737     };
738 
739     struct NameRecord {
740         mozilla::AutoSwap_PRUint16    platformID;   // Platform ID
741         mozilla::AutoSwap_PRUint16    encodingID;   // Platform-specific encoding ID
742         mozilla::AutoSwap_PRUint16    languageID;   // Language ID
743         mozilla::AutoSwap_PRUint16    nameID;       // Name ID.
744         mozilla::AutoSwap_PRUint16    length;       // String length (in bytes).
745         mozilla::AutoSwap_PRUint16    offset;       // String offset from start of storage
746                                                     // (in bytes).
747     };
748 
749     // for reading big-endian font data on either big or little-endian platforms
750 
751     static inline uint16_t
ReadShortAt(const uint8_t * aBuf,uint32_t aIndex)752     ReadShortAt(const uint8_t *aBuf, uint32_t aIndex)
753     {
754         return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
755     }
756 
757     static inline uint16_t
ReadShortAt16(const uint16_t * aBuf,uint32_t aIndex)758     ReadShortAt16(const uint16_t *aBuf, uint32_t aIndex)
759     {
760         const uint8_t *buf = reinterpret_cast<const uint8_t*>(aBuf);
761         uint32_t index = aIndex << 1;
762         return (buf[index] << 8) | buf[index+1];
763     }
764 
765     static inline uint32_t
ReadUint24At(const uint8_t * aBuf,uint32_t aIndex)766     ReadUint24At(const uint8_t *aBuf, uint32_t aIndex)
767     {
768         return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) |
769                 (aBuf[aIndex + 2]));
770     }
771 
772     static inline uint32_t
ReadLongAt(const uint8_t * aBuf,uint32_t aIndex)773     ReadLongAt(const uint8_t *aBuf, uint32_t aIndex)
774     {
775         return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
776                 (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
777     }
778 
779     static nsresult
780     ReadCMAPTableFormat10(const uint8_t *aBuf, uint32_t aLength,
781                           gfxSparseBitSet& aCharacterMap);
782 
783     static nsresult
784     ReadCMAPTableFormat12(const uint8_t *aBuf, uint32_t aLength,
785                           gfxSparseBitSet& aCharacterMap);
786 
787     static nsresult
788     ReadCMAPTableFormat4(const uint8_t *aBuf, uint32_t aLength,
789                          gfxSparseBitSet& aCharacterMap);
790 
791     static nsresult
792     ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength,
793                           mozilla::UniquePtr<uint8_t[]>& aTable);
794 
795     static uint32_t
796     FindPreferredSubtable(const uint8_t *aBuf, uint32_t aBufLength,
797                           uint32_t *aTableOffset, uint32_t *aUVSTableOffset,
798                           bool *aSymbolEncoding);
799 
800     static nsresult
801     ReadCMAP(const uint8_t *aBuf, uint32_t aBufLength,
802              gfxSparseBitSet& aCharacterMap,
803              uint32_t& aUVSOffset,
804              bool& aUnicodeFont, bool& aSymbolFont);
805 
806     static uint32_t
807     MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh);
808 
809     static uint32_t
810     MapCharToGlyphFormat10(const uint8_t *aBuf, uint32_t aCh);
811 
812     static uint32_t
813     MapCharToGlyphFormat12(const uint8_t *aBuf, uint32_t aCh);
814 
815     static uint16_t
816     MapUVSToGlyphFormat14(const uint8_t *aBuf, uint32_t aCh, uint32_t aVS);
817 
818     // sCJKCompatSVSTable is a 'cmap' format 14 subtable that maps
819     // <char + var-selector> pairs to the corresponding Unicode
820     // compatibility ideograph codepoints.
821     static MOZ_ALWAYS_INLINE uint32_t
GetUVSFallback(uint32_t aCh,uint32_t aVS)822     GetUVSFallback(uint32_t aCh, uint32_t aVS) {
823         aCh = MapUVSToGlyphFormat14(sCJKCompatSVSTable, aCh, aVS);
824         return aCh >= 0xFB00 ? aCh + (0x2F800 - 0xFB00) : aCh;
825     }
826 
827     static uint32_t
828     MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
829                    uint32_t aUnicode, uint32_t aVarSelector = 0);
830 
831 #ifdef XP_WIN
832     // determine whether a font (which has already been sanitized, so is known
833     // to be a valid sfnt) is CFF format rather than TrueType
834     static bool
835     IsCffFont(const uint8_t* aFontData);
836 #endif
837 
838     // determine the format of font data
839     static gfxUserFontType
840     DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontDataLength);
841 
842     // Read the fullname from the sfnt data (used to save the original name
843     // prior to renaming the font for installation).
844     // This is called with sfnt data that has already been validated,
845     // so it should always succeed in finding the name table.
846     static nsresult
847     GetFullNameFromSFNT(const uint8_t* aFontData, uint32_t aLength,
848                         nsAString& aFullName);
849 
850     // helper to get fullname from name table, constructing from family+style
851     // if no explicit fullname is present
852     static nsresult
853     GetFullNameFromTable(hb_blob_t *aNameTable,
854                          nsAString& aFullName);
855 
856     // helper to get family name from name table
857     static nsresult
858     GetFamilyNameFromTable(hb_blob_t *aNameTable,
859                            nsAString& aFamilyName);
860 
861     // Find the table directory entry for a given table tag, in a (validated)
862     // buffer of 'sfnt' data. Returns null if the tag is not present.
863     static mozilla::TableDirEntry*
864     FindTableDirEntry(const void* aFontData, uint32_t aTableTag);
865 
866     // Return a blob that wraps a table found within a buffer of font data.
867     // The blob does NOT own its data; caller guarantees that the buffer
868     // will remain valid at least as long as the blob.
869     // Returns null if the specified table is not found.
870     // This method assumes aFontData is valid 'sfnt' data; before using this,
871     // caller is responsible to do any sanitization/validation necessary.
872     static hb_blob_t*
873     GetTableFromFontData(const void* aFontData, uint32_t aTableTag);
874 
875     // create a new name table and build a new font with that name table
876     // appended on the end, returns true on success
877     static nsresult
878     RenameFont(const nsAString& aName, const uint8_t *aFontData,
879                uint32_t aFontDataLength, FallibleTArray<uint8_t> *aNewFont);
880 
881     // read all names matching aNameID, returning in aNames array
882     static nsresult
883     ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID,
884               int32_t aPlatformID, nsTArray<nsString>& aNames);
885 
886     // reads English or first name matching aNameID, returning in aName
887     // platform based on OS
888     static nsresult
889     ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID,
890                       nsString& aName);
891 
892     static nsresult
893     ReadCanonicalName(const char *aNameData, uint32_t aDataLen,
894                       uint32_t aNameID, nsString& aName);
895 
896     // convert a name from the raw name table data into an nsString,
897     // provided we know how; return true if successful, or false
898     // if we can't handle the encoding
899     static bool
900     DecodeFontName(const char *aBuf, int32_t aLength,
901                    uint32_t aPlatformCode, uint32_t aScriptCode,
902                    uint32_t aLangCode, nsAString& dest);
903 
IsJoinCauser(uint32_t ch)904     static inline bool IsJoinCauser(uint32_t ch) {
905         return (ch == 0x200D);
906     }
907 
IsJoinControl(uint32_t ch)908     static inline bool IsJoinControl(uint32_t ch) {
909         return (ch == 0x200C || ch == 0x200D);
910     }
911 
912     enum {
913         kUnicodeVS1 = 0xFE00,
914         kUnicodeVS16 = 0xFE0F,
915         kUnicodeVS17 = 0xE0100,
916         kUnicodeVS256 = 0xE01EF
917     };
918 
IsVarSelector(uint32_t ch)919     static inline bool IsVarSelector(uint32_t ch) {
920         return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
921                (ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
922     }
923 
924     enum {
925         kUnicodeRegionalIndicatorA = 0x1F1E6,
926         kUnicodeRegionalIndicatorZ = 0x1F1FF
927     };
928 
IsRegionalIndicator(uint32_t aCh)929     static inline bool IsRegionalIndicator(uint32_t aCh) {
930         return aCh >= kUnicodeRegionalIndicatorA &&
931                aCh <= kUnicodeRegionalIndicatorZ;
932     }
933 
IsInvalid(uint32_t ch)934     static inline bool IsInvalid(uint32_t ch) {
935         return (ch == 0xFFFD);
936     }
937 
938     // Font code may want to know if there is the potential for bidi behavior
939     // to be triggered by any of the characters in a text run; this can be
940     // used to test that possibility.
941     enum {
942         kUnicodeBidiScriptsStart = 0x0590,
943         kUnicodeBidiScriptsEnd = 0x08FF,
944         kUnicodeBidiPresentationStart = 0xFB1D,
945         kUnicodeBidiPresentationEnd = 0xFEFC,
946         kUnicodeFirstHighSurrogateBlock = 0xD800,
947         kUnicodeRLM = 0x200F,
948         kUnicodeRLE = 0x202B,
949         kUnicodeRLO = 0x202E
950     };
951 
PotentialRTLChar(char16_t aCh)952     static inline bool PotentialRTLChar(char16_t aCh) {
953         if (aCh >= kUnicodeBidiScriptsStart && aCh <= kUnicodeBidiScriptsEnd)
954             // bidi scripts Hebrew, Arabic, Syriac, Thaana, N'Ko are all encoded together
955             return true;
956 
957         if (aCh == kUnicodeRLM || aCh == kUnicodeRLE || aCh == kUnicodeRLO)
958             // directional controls that trigger bidi layout
959             return true;
960 
961         if (aCh >= kUnicodeBidiPresentationStart &&
962             aCh <= kUnicodeBidiPresentationEnd)
963             // presentation forms of Arabic and Hebrew letters
964             return true;
965 
966         if ((aCh & 0xFF00) == kUnicodeFirstHighSurrogateBlock)
967             // surrogate that could be part of a bidi supplementary char
968             // (Cypriot, Aramaic, Phoenecian, etc)
969             return true;
970 
971         // otherwise we know this char cannot trigger bidi reordering
972         return false;
973     }
974 
975     // parse a simple list of font family names into
976     // an array of strings
977     static void ParseFontList(const nsAString& aFamilyList,
978                               nsTArray<nsString>& aFontList);
979 
980     // for a given font list pref name, append list of font names
981     static void AppendPrefsFontList(const char *aPrefName,
982                                     nsTArray<nsString>& aFontList);
983 
984     // for a given font list pref name, initialize a list of font names
985     static void GetPrefsFontList(const char *aPrefName,
986                                  nsTArray<nsString>& aFontList);
987 
988     // generate a unique font name
989     static nsresult MakeUniqueUserFontName(nsAString& aName);
990 
991     // for color layer from glyph using COLR and CPAL tables
992     static bool ValidateColorGlyphs(hb_blob_t* aCOLR, hb_blob_t* aCPAL);
993     static bool GetColorGlyphLayers(hb_blob_t* aCOLR,
994                                     hb_blob_t* aCPAL,
995                                     uint32_t aGlyphId,
996                                     const mozilla::gfx::Color& aDefaultColor,
997                                     nsTArray<uint16_t> &aGlyphs,
998                                     nsTArray<mozilla::gfx::Color> &aColors);
999 
1000 protected:
1001     friend struct MacCharsetMappingComparator;
1002 
1003     static nsresult
1004     ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID,
1005               int32_t aLangID, int32_t aPlatformID, nsTArray<nsString>& aNames);
1006 
1007     // convert opentype name-table platform/encoding/language values to a charset name
1008     // we can use to convert the name data to unicode, or "" if data is UTF16BE
1009     static const char*
1010     GetCharsetForFontName(uint16_t aPlatform, uint16_t aScript, uint16_t aLanguage);
1011 
1012     struct MacFontNameCharsetMapping {
1013         uint16_t    mEncoding;
1014         uint16_t    mLanguage;
1015         const char *mCharsetName;
1016 
1017         bool operator<(const MacFontNameCharsetMapping& rhs) const {
1018             return (mEncoding < rhs.mEncoding) ||
1019                    ((mEncoding == rhs.mEncoding) && (mLanguage < rhs.mLanguage));
1020         }
1021     };
1022     static const MacFontNameCharsetMapping gMacFontNameCharsets[];
1023     static const char* gISOFontNameCharsets[];
1024     static const char* gMSFontNameCharsets[];
1025 };
1026 
1027 #endif /* GFX_FONT_UTILS_H */
1028