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