Coverage Report

Created: 2018-09-25 14:53

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