/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 */ |