Line data Source code
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 0 : 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 {
35 0 : Block(const Block& aBlock) { memcpy(mBits, aBlock.mBits, sizeof(mBits)); }
36 3 : explicit Block(unsigned char memsetValue = 0) { memset(mBits, memsetValue, BLOCK_SIZE); }
37 : uint8_t mBits[BLOCK_SIZE];
38 : };
39 :
40 : public:
41 561 : 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].get();
47 : if (block) {
48 : mBlocks[i] = mozilla::MakeUnique<Block>(*block);
49 : }
50 : }
51 : }
52 :
53 0 : bool Equals(const gfxSparseBitSet *aOther) const {
54 0 : if (mBlocks.Length() != aOther->mBlocks.Length()) {
55 0 : return false;
56 : }
57 0 : size_t n = mBlocks.Length();
58 0 : for (size_t i = 0; i < n; ++i) {
59 0 : const Block *b1 = mBlocks[i].get();
60 0 : const Block *b2 = aOther->mBlocks[i].get();
61 0 : if (!b1 != !b2) {
62 0 : return false;
63 : }
64 0 : if (!b1) {
65 0 : continue;
66 : }
67 0 : if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) {
68 0 : return false;
69 : }
70 : }
71 0 : return true;
72 : }
73 :
74 0 : bool test(uint32_t aIndex) const {
75 0 : NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
76 0 : uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
77 0 : if (blockIndex >= mBlocks.Length()) {
78 0 : return false;
79 : }
80 0 : const Block *block = mBlocks[blockIndex].get();
81 0 : if (!block) {
82 0 : return false;
83 : }
84 0 : 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 :
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 :
158 0 : void set(uint32_t aIndex) {
159 0 : uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS;
160 0 : if (blockIndex >= mBlocks.Length()) {
161 0 : mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
162 : }
163 0 : Block *block = mBlocks[blockIndex].get();
164 0 : if (!block) {
165 0 : block = new Block;
166 0 : mBlocks[blockIndex].reset(block);
167 : }
168 0 : block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
169 0 : }
170 :
171 : void set(uint32_t aIndex, bool aValue) {
172 : if (aValue)
173 : set(aIndex);
174 : else
175 : clear(aIndex);
176 : }
177 :
178 6 : void SetRange(uint32_t aStart, uint32_t aEnd) {
179 6 : const uint32_t startIndex = aStart/BLOCK_SIZE_BITS;
180 6 : const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS;
181 :
182 6 : if (endIndex >= mBlocks.Length()) {
183 3 : uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length();
184 3 : mBlocks.AppendElements(numNewBlocks);
185 : }
186 :
187 12 : for (uint32_t i = startIndex; i <= endIndex; ++i) {
188 6 : const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS;
189 6 : const uint32_t blockLastBit = blockFirstBit + BLOCK_SIZE_BITS - 1;
190 :
191 6 : Block *block = mBlocks[i].get();
192 6 : if (!block) {
193 : bool fullBlock =
194 3 : (aStart <= blockFirstBit && aEnd >= blockLastBit);
195 :
196 3 : block = new Block(fullBlock ? 0xFF : 0);
197 3 : mBlocks[i].reset(block);
198 :
199 3 : if (fullBlock) {
200 0 : continue;
201 : }
202 : }
203 :
204 6 : const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
205 6 : const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
206 :
207 201 : for (uint32_t bit = start; bit <= end; ++bit) {
208 195 : block->mBits[bit>>3] |= 1 << (bit & 0x7);
209 : }
210 : }
211 6 : }
212 :
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 :
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 :
253 0 : size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
254 0 : size_t total = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
255 0 : for (uint32_t i = 0; i < mBlocks.Length(); i++) {
256 0 : if (mBlocks[i]) {
257 0 : total += aMallocSizeOf(mBlocks[i].get());
258 : }
259 : }
260 0 : return total;
261 : }
262 :
263 0 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
264 0 : return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
265 : }
266 :
267 : // clear out all blocks in the array
268 3 : void reset() {
269 : uint32_t i;
270 3 : for (i = 0; i < mBlocks.Length(); i++) {
271 0 : mBlocks[i] = nullptr;
272 : }
273 3 : }
274 :
275 : // set this bitset to the union of its current contents and another
276 0 : void Union(const gfxSparseBitSet& aBitset) {
277 : // ensure mBlocks is large enough
278 0 : uint32_t blockCount = aBitset.mBlocks.Length();
279 0 : if (blockCount > mBlocks.Length()) {
280 0 : uint32_t needed = blockCount - mBlocks.Length();
281 0 : mBlocks.AppendElements(needed);
282 : }
283 : // for each block that may be present in aBitset...
284 0 : for (uint32_t i = 0; i < blockCount; ++i) {
285 : // if it is missing (implicitly empty), just skip
286 0 : if (!aBitset.mBlocks[i]) {
287 0 : continue;
288 : }
289 : // if the block is missing in this set, just copy the other
290 0 : if (!mBlocks[i]) {
291 0 : mBlocks[i] = mozilla::MakeUnique<Block>(*aBitset.mBlocks[i]);
292 0 : continue;
293 : }
294 : // else set existing block to the union of both
295 0 : uint32_t *dst = reinterpret_cast<uint32_t*>(mBlocks[i]->mBits);
296 : const uint32_t *src =
297 0 : reinterpret_cast<const uint32_t*>(aBitset.mBlocks[i]->mBits);
298 0 : for (uint32_t j = 0; j < BLOCK_SIZE / 4; ++j) {
299 0 : dst[j] |= src[j];
300 : }
301 : }
302 0 : }
303 :
304 0 : void Compact() {
305 0 : mBlocks.Compact();
306 0 : }
307 :
308 0 : uint32_t GetChecksum() const {
309 0 : uint32_t check = adler32(0, Z_NULL, 0);
310 0 : for (uint32_t i = 0; i < mBlocks.Length(); i++) {
311 0 : if (mBlocks[i]) {
312 0 : const Block *block = mBlocks[i].get();
313 0 : check = adler32(check, (uint8_t*) (&i), 4);
314 0 : check = adler32(check, (uint8_t*) block, sizeof(Block));
315 : }
316 : }
317 0 : 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 0 : MOZ_IMPLICIT AutoSwap_PRUint16(uint16_t aValue)
341 0 : {
342 0 : value = mozilla::NativeEndian::swapToBigEndian(aValue);
343 0 : }
344 : #endif
345 2 : operator uint16_t() const
346 : {
347 2 : return mozilla::NativeEndian::swapFromBigEndian(value);
348 : }
349 :
350 0 : operator uint32_t() const
351 : {
352 0 : return mozilla::NativeEndian::swapFromBigEndian(value);
353 : }
354 :
355 0 : operator uint64_t() const
356 : {
357 0 : 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
377 0 : operator int16_t() const
378 : {
379 0 : return mozilla::NativeEndian::swapFromBigEndian(value);
380 : }
381 :
382 : 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 0 : MOZ_IMPLICIT AutoSwap_PRUint32(uint32_t aValue)
400 0 : {
401 0 : value = mozilla::NativeEndian::swapToBigEndian(aValue);
402 0 : }
403 : #endif
404 0 : operator uint32_t() const
405 : {
406 0 : 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
426 : 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
448 : 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 {
458 0 : operator uint32_t() const { return value[0] << 16 | value[1] << 8 | value[2]; }
459 : private:
460 : 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
633 0 : FindHighestBit(uint32_t value)
634 : {
635 : // propagate highest bit into all lower bits of the value
636 0 : value |= (value >> 1);
637 0 : value |= (value >> 2);
638 0 : value |= (value >> 4);
639 0 : value |= (value >> 8);
640 0 : value |= (value >> 16);
641 : // isolate the leftmost bit
642 0 : 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
752 0 : ReadShortAt(const uint8_t *aBuf, uint32_t aIndex)
753 : {
754 0 : return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
755 : }
756 :
757 : static inline uint16_t
758 0 : ReadShortAt16(const uint16_t *aBuf, uint32_t aIndex)
759 : {
760 0 : const uint8_t *buf = reinterpret_cast<const uint8_t*>(aBuf);
761 0 : uint32_t index = aIndex << 1;
762 0 : return (buf[index] << 8) | buf[index+1];
763 : }
764 :
765 : static inline uint32_t
766 0 : ReadUint24At(const uint8_t *aBuf, uint32_t aIndex)
767 : {
768 0 : return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) |
769 0 : (aBuf[aIndex + 2]));
770 : }
771 :
772 : static inline uint32_t
773 0 : ReadLongAt(const uint8_t *aBuf, uint32_t aIndex)
774 : {
775 0 : return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
776 0 : (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 : ReadCMAPTableFormat12or13(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 : MapCharToGlyphFormat12or13(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
822 0 : GetUVSFallback(uint32_t aCh, uint32_t aVS) {
823 0 : aCh = MapUVSToGlyphFormat14(sCJKCompatSVSTable, aCh, aVS);
824 0 : 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 :
904 658 : static inline bool IsJoinCauser(uint32_t ch) {
905 658 : return (ch == 0x200D);
906 : }
907 :
908 658 : static inline bool IsJoinControl(uint32_t ch) {
909 658 : return (ch == 0x200C || ch == 0x200D);
910 : }
911 :
912 : enum {
913 : kUnicodeVS1 = 0xFE00,
914 : kUnicodeVS16 = 0xFE0F,
915 : kUnicodeVS17 = 0xE0100,
916 : kUnicodeVS256 = 0xE01EF
917 : };
918 :
919 658 : static inline bool IsVarSelector(uint32_t ch) {
920 658 : return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
921 658 : (ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
922 : }
923 :
924 : enum {
925 : kUnicodeRegionalIndicatorA = 0x1F1E6,
926 : kUnicodeRegionalIndicatorZ = 0x1F1FF
927 : };
928 :
929 0 : static inline bool IsRegionalIndicator(uint32_t aCh) {
930 0 : return aCh >= kUnicodeRegionalIndicatorA &&
931 0 : aCh <= kUnicodeRegionalIndicatorZ;
932 : }
933 :
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 :
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 0 : bool operator<(const MacFontNameCharsetMapping& rhs) const {
1018 0 : return (mEncoding < rhs.mEncoding) ||
1019 0 : ((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 */
|