1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxFontUtils.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,955 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef GFX_FONT_UTILS_H 1.10 +#define GFX_FONT_UTILS_H 1.11 + 1.12 +#include "gfxPlatform.h" 1.13 +#include "nsComponentManagerUtils.h" 1.14 +#include "nsTArray.h" 1.15 +#include "nsAutoPtr.h" 1.16 +#include "mozilla/Likely.h" 1.17 +#include "mozilla/Endian.h" 1.18 +#include "mozilla/MemoryReporting.h" 1.19 + 1.20 +#include "zlib.h" 1.21 +#include <algorithm> 1.22 + 1.23 +/* Bug 341128 - w32api defines min/max which causes problems with <bitset> */ 1.24 +#ifdef __MINGW32__ 1.25 +#undef min 1.26 +#undef max 1.27 +#endif 1.28 + 1.29 +typedef struct hb_blob_t hb_blob_t; 1.30 + 1.31 +class gfxSparseBitSet { 1.32 +private: 1.33 + enum { BLOCK_SIZE = 32 }; // ==> 256 codepoints per block 1.34 + enum { BLOCK_SIZE_BITS = BLOCK_SIZE * 8 }; 1.35 + enum { BLOCK_INDEX_SHIFT = 8 }; 1.36 + 1.37 + struct Block { 1.38 + Block(const Block& aBlock) { memcpy(mBits, aBlock.mBits, sizeof(mBits)); } 1.39 + Block(unsigned char memsetValue = 0) { memset(mBits, memsetValue, BLOCK_SIZE); } 1.40 + uint8_t mBits[BLOCK_SIZE]; 1.41 + }; 1.42 + 1.43 +public: 1.44 + gfxSparseBitSet() { } 1.45 + gfxSparseBitSet(const gfxSparseBitSet& aBitset) { 1.46 + uint32_t len = aBitset.mBlocks.Length(); 1.47 + mBlocks.AppendElements(len); 1.48 + for (uint32_t i = 0; i < len; ++i) { 1.49 + Block *block = aBitset.mBlocks[i]; 1.50 + if (block) 1.51 + mBlocks[i] = new Block(*block); 1.52 + } 1.53 + } 1.54 + 1.55 + bool Equals(const gfxSparseBitSet *aOther) const { 1.56 + if (mBlocks.Length() != aOther->mBlocks.Length()) { 1.57 + return false; 1.58 + } 1.59 + size_t n = mBlocks.Length(); 1.60 + for (size_t i = 0; i < n; ++i) { 1.61 + const Block *b1 = mBlocks[i]; 1.62 + const Block *b2 = aOther->mBlocks[i]; 1.63 + if (!b1 != !b2) { 1.64 + return false; 1.65 + } 1.66 + if (!b1) { 1.67 + continue; 1.68 + } 1.69 + if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) { 1.70 + return false; 1.71 + } 1.72 + } 1.73 + return true; 1.74 + } 1.75 + 1.76 + bool test(uint32_t aIndex) const { 1.77 + NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad"); 1.78 + uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS; 1.79 + if (blockIndex >= mBlocks.Length()) 1.80 + return false; 1.81 + Block *block = mBlocks[blockIndex]; 1.82 + if (!block) 1.83 + return false; 1.84 + return ((block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0; 1.85 + } 1.86 + 1.87 +#if PR_LOGGING 1.88 + // dump out contents of bitmap 1.89 + void Dump(const char* aPrefix, eGfxLog aWhichLog) const; 1.90 +#endif 1.91 + 1.92 + bool TestRange(uint32_t aStart, uint32_t aEnd) { 1.93 + uint32_t startBlock, endBlock, blockLen; 1.94 + 1.95 + // start point is beyond the end of the block array? return false immediately 1.96 + startBlock = aStart >> BLOCK_INDEX_SHIFT; 1.97 + blockLen = mBlocks.Length(); 1.98 + if (startBlock >= blockLen) return false; 1.99 + 1.100 + // check for blocks in range, if none, return false 1.101 + uint32_t blockIndex; 1.102 + bool hasBlocksInRange = false; 1.103 + 1.104 + endBlock = aEnd >> BLOCK_INDEX_SHIFT; 1.105 + blockIndex = startBlock; 1.106 + for (blockIndex = startBlock; blockIndex <= endBlock; blockIndex++) { 1.107 + if (blockIndex < blockLen && mBlocks[blockIndex]) 1.108 + hasBlocksInRange = true; 1.109 + } 1.110 + if (!hasBlocksInRange) return false; 1.111 + 1.112 + Block *block; 1.113 + uint32_t i, start, end; 1.114 + 1.115 + // first block, check bits 1.116 + if ((block = mBlocks[startBlock])) { 1.117 + start = aStart; 1.118 + end = std::min(aEnd, ((startBlock+1) << BLOCK_INDEX_SHIFT) - 1); 1.119 + for (i = start; i <= end; i++) { 1.120 + if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7))) 1.121 + return true; 1.122 + } 1.123 + } 1.124 + if (endBlock == startBlock) return false; 1.125 + 1.126 + // [2..n-1] blocks check bytes 1.127 + for (blockIndex = startBlock + 1; blockIndex < endBlock; blockIndex++) { 1.128 + uint32_t index; 1.129 + 1.130 + if (blockIndex >= blockLen || !(block = mBlocks[blockIndex])) continue; 1.131 + for (index = 0; index < BLOCK_SIZE; index++) { 1.132 + if (block->mBits[index]) 1.133 + return true; 1.134 + } 1.135 + } 1.136 + 1.137 + // last block, check bits 1.138 + if (endBlock < blockLen && (block = mBlocks[endBlock])) { 1.139 + start = endBlock << BLOCK_INDEX_SHIFT; 1.140 + end = aEnd; 1.141 + for (i = start; i <= end; i++) { 1.142 + if ((block->mBits[(i>>3) & (BLOCK_SIZE - 1)]) & (1 << (i & 0x7))) 1.143 + return true; 1.144 + } 1.145 + } 1.146 + 1.147 + return false; 1.148 + } 1.149 + 1.150 + void set(uint32_t aIndex) { 1.151 + uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS; 1.152 + if (blockIndex >= mBlocks.Length()) { 1.153 + nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length()); 1.154 + if (MOZ_UNLIKELY(!blocks)) // OOM 1.155 + return; 1.156 + } 1.157 + Block *block = mBlocks[blockIndex]; 1.158 + if (!block) { 1.159 + block = new Block; 1.160 + mBlocks[blockIndex] = block; 1.161 + } 1.162 + block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7); 1.163 + } 1.164 + 1.165 + void set(uint32_t aIndex, bool aValue) { 1.166 + if (aValue) 1.167 + set(aIndex); 1.168 + else 1.169 + clear(aIndex); 1.170 + } 1.171 + 1.172 + void SetRange(uint32_t aStart, uint32_t aEnd) { 1.173 + const uint32_t startIndex = aStart/BLOCK_SIZE_BITS; 1.174 + const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS; 1.175 + 1.176 + if (endIndex >= mBlocks.Length()) { 1.177 + uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length(); 1.178 + nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks); 1.179 + if (MOZ_UNLIKELY(!blocks)) // OOM 1.180 + return; 1.181 + } 1.182 + 1.183 + for (uint32_t i = startIndex; i <= endIndex; ++i) { 1.184 + const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS; 1.185 + const uint32_t blockLastBit = blockFirstBit + BLOCK_SIZE_BITS - 1; 1.186 + 1.187 + Block *block = mBlocks[i]; 1.188 + if (!block) { 1.189 + bool fullBlock = false; 1.190 + if (aStart <= blockFirstBit && aEnd >= blockLastBit) 1.191 + fullBlock = true; 1.192 + 1.193 + block = new Block(fullBlock ? 0xFF : 0); 1.194 + mBlocks[i] = block; 1.195 + 1.196 + if (fullBlock) 1.197 + continue; 1.198 + } 1.199 + 1.200 + const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0; 1.201 + const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1); 1.202 + 1.203 + for (uint32_t bit = start; bit <= end; ++bit) { 1.204 + block->mBits[bit>>3] |= 1 << (bit & 0x7); 1.205 + } 1.206 + } 1.207 + } 1.208 + 1.209 + void clear(uint32_t aIndex) { 1.210 + uint32_t blockIndex = aIndex/BLOCK_SIZE_BITS; 1.211 + if (blockIndex >= mBlocks.Length()) { 1.212 + nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length()); 1.213 + if (MOZ_UNLIKELY(!blocks)) // OOM 1.214 + return; 1.215 + } 1.216 + Block *block = mBlocks[blockIndex]; 1.217 + if (!block) { 1.218 + return; 1.219 + } 1.220 + block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] &= ~(1 << (aIndex & 0x7)); 1.221 + } 1.222 + 1.223 + void ClearRange(uint32_t aStart, uint32_t aEnd) { 1.224 + const uint32_t startIndex = aStart/BLOCK_SIZE_BITS; 1.225 + const uint32_t endIndex = aEnd/BLOCK_SIZE_BITS; 1.226 + 1.227 + if (endIndex >= mBlocks.Length()) { 1.228 + uint32_t numNewBlocks = endIndex + 1 - mBlocks.Length(); 1.229 + nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks); 1.230 + if (MOZ_UNLIKELY(!blocks)) // OOM 1.231 + return; 1.232 + } 1.233 + 1.234 + for (uint32_t i = startIndex; i <= endIndex; ++i) { 1.235 + const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS; 1.236 + 1.237 + Block *block = mBlocks[i]; 1.238 + if (!block) { 1.239 + // any nonexistent block is implicitly all clear, 1.240 + // so there's no need to even create it 1.241 + continue; 1.242 + } 1.243 + 1.244 + const uint32_t start = aStart > blockFirstBit ? aStart - blockFirstBit : 0; 1.245 + const uint32_t end = std::min<uint32_t>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1); 1.246 + 1.247 + for (uint32_t bit = start; bit <= end; ++bit) { 1.248 + block->mBits[bit>>3] &= ~(1 << (bit & 0x7)); 1.249 + } 1.250 + } 1.251 + } 1.252 + 1.253 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { 1.254 + size_t total = mBlocks.SizeOfExcludingThis(aMallocSizeOf); 1.255 + for (uint32_t i = 0; i < mBlocks.Length(); i++) { 1.256 + if (mBlocks[i]) { 1.257 + total += aMallocSizeOf(mBlocks[i]); 1.258 + } 1.259 + } 1.260 + return total; 1.261 + } 1.262 + 1.263 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { 1.264 + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 1.265 + } 1.266 + 1.267 + // clear out all blocks in the array 1.268 + void reset() { 1.269 + uint32_t i; 1.270 + for (i = 0; i < mBlocks.Length(); i++) 1.271 + mBlocks[i] = nullptr; 1.272 + } 1.273 + 1.274 + // set this bitset to the union of its current contents and another 1.275 + void Union(const gfxSparseBitSet& aBitset) { 1.276 + // ensure mBlocks is large enough 1.277 + uint32_t blockCount = aBitset.mBlocks.Length(); 1.278 + if (blockCount > mBlocks.Length()) { 1.279 + uint32_t needed = blockCount - mBlocks.Length(); 1.280 + nsAutoPtr<Block> *blocks = mBlocks.AppendElements(needed); 1.281 + if (MOZ_UNLIKELY(!blocks)) { // OOM 1.282 + return; 1.283 + } 1.284 + } 1.285 + // for each block that may be present in aBitset... 1.286 + for (uint32_t i = 0; i < blockCount; ++i) { 1.287 + // if it is missing (implicitly empty), just skip 1.288 + if (!aBitset.mBlocks[i]) { 1.289 + continue; 1.290 + } 1.291 + // if the block is missing in this set, just copy the other 1.292 + if (!mBlocks[i]) { 1.293 + mBlocks[i] = new Block(*aBitset.mBlocks[i]); 1.294 + continue; 1.295 + } 1.296 + // else set existing block to the union of both 1.297 + uint32_t *dst = reinterpret_cast<uint32_t*>(mBlocks[i]->mBits); 1.298 + const uint32_t *src = 1.299 + reinterpret_cast<const uint32_t*>(aBitset.mBlocks[i]->mBits); 1.300 + for (uint32_t j = 0; j < BLOCK_SIZE / 4; ++j) { 1.301 + dst[j] |= src[j]; 1.302 + } 1.303 + } 1.304 + } 1.305 + 1.306 + void Compact() { 1.307 + mBlocks.Compact(); 1.308 + } 1.309 + 1.310 + uint32_t GetChecksum() const { 1.311 + uint32_t check = adler32(0, Z_NULL, 0); 1.312 + for (uint32_t i = 0; i < mBlocks.Length(); i++) { 1.313 + if (mBlocks[i]) { 1.314 + const Block *block = mBlocks[i]; 1.315 + check = adler32(check, (uint8_t*) (&i), 4); 1.316 + check = adler32(check, (uint8_t*) block, sizeof(Block)); 1.317 + } 1.318 + } 1.319 + return check; 1.320 + } 1.321 + 1.322 +private: 1.323 + nsTArray< nsAutoPtr<Block> > mBlocks; 1.324 +}; 1.325 + 1.326 +#define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) 1.327 + 1.328 +namespace mozilla { 1.329 + 1.330 +// Byte-swapping types and name table structure definitions moved from 1.331 +// gfxFontUtils.cpp to .h file so that gfxFont.cpp can also refer to them 1.332 +#pragma pack(1) 1.333 + 1.334 +struct AutoSwap_PRUint16 { 1.335 +#ifdef __SUNPRO_CC 1.336 + AutoSwap_PRUint16& operator = (const uint16_t aValue) 1.337 + { 1.338 + this->value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.339 + return *this; 1.340 + } 1.341 +#else 1.342 + AutoSwap_PRUint16(uint16_t aValue) 1.343 + { 1.344 + value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.345 + } 1.346 +#endif 1.347 + operator uint16_t() const 1.348 + { 1.349 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.350 + } 1.351 + 1.352 + operator uint32_t() const 1.353 + { 1.354 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.355 + } 1.356 + 1.357 + operator uint64_t() const 1.358 + { 1.359 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.360 + } 1.361 + 1.362 +private: 1.363 + uint16_t value; 1.364 +}; 1.365 + 1.366 +struct AutoSwap_PRInt16 { 1.367 +#ifdef __SUNPRO_CC 1.368 + AutoSwap_PRInt16& operator = (const int16_t aValue) 1.369 + { 1.370 + this->value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.371 + return *this; 1.372 + } 1.373 +#else 1.374 + AutoSwap_PRInt16(int16_t aValue) 1.375 + { 1.376 + value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.377 + } 1.378 +#endif 1.379 + operator int16_t() const 1.380 + { 1.381 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.382 + } 1.383 + 1.384 + operator uint32_t() const 1.385 + { 1.386 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.387 + } 1.388 + 1.389 +private: 1.390 + int16_t value; 1.391 +}; 1.392 + 1.393 +struct AutoSwap_PRUint32 { 1.394 +#ifdef __SUNPRO_CC 1.395 + AutoSwap_PRUint32& operator = (const uint32_t aValue) 1.396 + { 1.397 + this->value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.398 + return *this; 1.399 + } 1.400 +#else 1.401 + AutoSwap_PRUint32(uint32_t aValue) 1.402 + { 1.403 + value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.404 + } 1.405 +#endif 1.406 + operator uint32_t() const 1.407 + { 1.408 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.409 + } 1.410 + 1.411 +private: 1.412 + uint32_t value; 1.413 +}; 1.414 + 1.415 +struct AutoSwap_PRInt32 { 1.416 +#ifdef __SUNPRO_CC 1.417 + AutoSwap_PRInt32& operator = (const int32_t aValue) 1.418 + { 1.419 + this->value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.420 + return *this; 1.421 + } 1.422 +#else 1.423 + AutoSwap_PRInt32(int32_t aValue) 1.424 + { 1.425 + value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.426 + } 1.427 +#endif 1.428 + operator int32_t() const 1.429 + { 1.430 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.431 + } 1.432 + 1.433 +private: 1.434 + int32_t value; 1.435 +}; 1.436 + 1.437 +struct AutoSwap_PRUint64 { 1.438 +#ifdef __SUNPRO_CC 1.439 + AutoSwap_PRUint64& operator = (const uint64_t aValue) 1.440 + { 1.441 + this->value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.442 + return *this; 1.443 + } 1.444 +#else 1.445 + AutoSwap_PRUint64(uint64_t aValue) 1.446 + { 1.447 + value = mozilla::NativeEndian::swapToBigEndian(aValue); 1.448 + } 1.449 +#endif 1.450 + operator uint64_t() const 1.451 + { 1.452 + return mozilla::NativeEndian::swapFromBigEndian(value); 1.453 + } 1.454 + 1.455 +private: 1.456 + uint64_t value; 1.457 +}; 1.458 + 1.459 +struct AutoSwap_PRUint24 { 1.460 + operator uint32_t() const { return value[0] << 16 | value[1] << 8 | value[2]; } 1.461 +private: 1.462 + AutoSwap_PRUint24() { } 1.463 + uint8_t value[3]; 1.464 +}; 1.465 + 1.466 +struct SFNTHeader { 1.467 + AutoSwap_PRUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0. 1.468 + AutoSwap_PRUint16 numTables; // Number of tables. 1.469 + AutoSwap_PRUint16 searchRange; // (Maximum power of 2 <= numTables) x 16. 1.470 + AutoSwap_PRUint16 entrySelector; // Log2(maximum power of 2 <= numTables). 1.471 + AutoSwap_PRUint16 rangeShift; // NumTables x 16-searchRange. 1.472 +}; 1.473 + 1.474 +struct TableDirEntry { 1.475 + AutoSwap_PRUint32 tag; // 4 -byte identifier. 1.476 + AutoSwap_PRUint32 checkSum; // CheckSum for this table. 1.477 + AutoSwap_PRUint32 offset; // Offset from beginning of TrueType font file. 1.478 + AutoSwap_PRUint32 length; // Length of this table. 1.479 +}; 1.480 + 1.481 +struct HeadTable { 1.482 + enum { 1.483 + HEAD_VERSION = 0x00010000, 1.484 + HEAD_MAGIC_NUMBER = 0x5F0F3CF5, 1.485 + HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA 1.486 + }; 1.487 + 1.488 + AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0. 1.489 + AutoSwap_PRUint32 fontRevision; // Set by font manufacturer. 1.490 + AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum. 1.491 + AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5. 1.492 + AutoSwap_PRUint16 flags; 1.493 + AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines. 1.494 + AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer 1.495 + AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer 1.496 + AutoSwap_PRInt16 xMin; // For all glyph bounding boxes. 1.497 + AutoSwap_PRInt16 yMin; // For all glyph bounding boxes. 1.498 + AutoSwap_PRInt16 xMax; // For all glyph bounding boxes. 1.499 + AutoSwap_PRInt16 yMax; // For all glyph bounding boxes. 1.500 + AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1); 1.501 + AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels. 1.502 + AutoSwap_PRInt16 fontDirectionHint; 1.503 + AutoSwap_PRInt16 indexToLocFormat; 1.504 + AutoSwap_PRInt16 glyphDataFormat; 1.505 +}; 1.506 + 1.507 +struct OS2Table { 1.508 + AutoSwap_PRUint16 version; // 0004 = OpenType 1.5 1.509 + AutoSwap_PRInt16 xAvgCharWidth; 1.510 + AutoSwap_PRUint16 usWeightClass; 1.511 + AutoSwap_PRUint16 usWidthClass; 1.512 + AutoSwap_PRUint16 fsType; 1.513 + AutoSwap_PRInt16 ySubscriptXSize; 1.514 + AutoSwap_PRInt16 ySubscriptYSize; 1.515 + AutoSwap_PRInt16 ySubscriptXOffset; 1.516 + AutoSwap_PRInt16 ySubscriptYOffset; 1.517 + AutoSwap_PRInt16 ySuperscriptXSize; 1.518 + AutoSwap_PRInt16 ySuperscriptYSize; 1.519 + AutoSwap_PRInt16 ySuperscriptXOffset; 1.520 + AutoSwap_PRInt16 ySuperscriptYOffset; 1.521 + AutoSwap_PRInt16 yStrikeoutSize; 1.522 + AutoSwap_PRInt16 yStrikeoutPosition; 1.523 + AutoSwap_PRInt16 sFamilyClass; 1.524 + uint8_t panose[10]; 1.525 + AutoSwap_PRUint32 unicodeRange1; 1.526 + AutoSwap_PRUint32 unicodeRange2; 1.527 + AutoSwap_PRUint32 unicodeRange3; 1.528 + AutoSwap_PRUint32 unicodeRange4; 1.529 + uint8_t achVendID[4]; 1.530 + AutoSwap_PRUint16 fsSelection; 1.531 + AutoSwap_PRUint16 usFirstCharIndex; 1.532 + AutoSwap_PRUint16 usLastCharIndex; 1.533 + AutoSwap_PRInt16 sTypoAscender; 1.534 + AutoSwap_PRInt16 sTypoDescender; 1.535 + AutoSwap_PRInt16 sTypoLineGap; 1.536 + AutoSwap_PRUint16 usWinAscent; 1.537 + AutoSwap_PRUint16 usWinDescent; 1.538 + AutoSwap_PRUint32 codePageRange1; 1.539 + AutoSwap_PRUint32 codePageRange2; 1.540 + AutoSwap_PRInt16 sxHeight; 1.541 + AutoSwap_PRInt16 sCapHeight; 1.542 + AutoSwap_PRUint16 usDefaultChar; 1.543 + AutoSwap_PRUint16 usBreakChar; 1.544 + AutoSwap_PRUint16 usMaxContext; 1.545 +}; 1.546 + 1.547 +struct PostTable { 1.548 + AutoSwap_PRUint32 version; 1.549 + AutoSwap_PRInt32 italicAngle; 1.550 + AutoSwap_PRInt16 underlinePosition; 1.551 + AutoSwap_PRUint16 underlineThickness; 1.552 + AutoSwap_PRUint32 isFixedPitch; 1.553 + AutoSwap_PRUint32 minMemType42; 1.554 + AutoSwap_PRUint32 maxMemType42; 1.555 + AutoSwap_PRUint32 minMemType1; 1.556 + AutoSwap_PRUint32 maxMemType1; 1.557 +}; 1.558 + 1.559 +struct HheaTable { 1.560 + AutoSwap_PRUint32 version; 1.561 + AutoSwap_PRInt16 ascender; 1.562 + AutoSwap_PRInt16 descender; 1.563 + AutoSwap_PRInt16 lineGap; 1.564 + AutoSwap_PRUint16 advanceWidthMax; 1.565 + AutoSwap_PRInt16 minLeftSideBearing; 1.566 + AutoSwap_PRInt16 minRightSideBearing; 1.567 + AutoSwap_PRInt16 xMaxExtent; 1.568 + AutoSwap_PRInt16 caretSlopeRise; 1.569 + AutoSwap_PRInt16 caretSlopeRun; 1.570 + AutoSwap_PRInt16 caretOffset; 1.571 + AutoSwap_PRInt16 reserved1; 1.572 + AutoSwap_PRInt16 reserved2; 1.573 + AutoSwap_PRInt16 reserved3; 1.574 + AutoSwap_PRInt16 reserved4; 1.575 + AutoSwap_PRInt16 metricDataFormat; 1.576 + AutoSwap_PRUint16 numOfLongHorMetrics; 1.577 +}; 1.578 + 1.579 +struct MaxpTableHeader { 1.580 + AutoSwap_PRUint32 version; // CFF: 0x00005000; TrueType: 0x00010000 1.581 + AutoSwap_PRUint16 numGlyphs; 1.582 +// truetype version has additional fields that we don't currently use 1.583 +}; 1.584 + 1.585 +// old 'kern' table, supported on Windows 1.586 +// see http://www.microsoft.com/typography/otspec/kern.htm 1.587 +struct KernTableVersion0 { 1.588 + AutoSwap_PRUint16 version; // 0x0000 1.589 + AutoSwap_PRUint16 nTables; 1.590 +}; 1.591 + 1.592 +struct KernTableSubtableHeaderVersion0 { 1.593 + AutoSwap_PRUint16 version; 1.594 + AutoSwap_PRUint16 length; 1.595 + AutoSwap_PRUint16 coverage; 1.596 +}; 1.597 + 1.598 +// newer Mac-only 'kern' table, ignored by Windows 1.599 +// see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6kern.html 1.600 +struct KernTableVersion1 { 1.601 + AutoSwap_PRUint32 version; // 0x00010000 1.602 + AutoSwap_PRUint32 nTables; 1.603 +}; 1.604 + 1.605 +struct KernTableSubtableHeaderVersion1 { 1.606 + AutoSwap_PRUint32 length; 1.607 + AutoSwap_PRUint16 coverage; 1.608 + AutoSwap_PRUint16 tupleIndex; 1.609 +}; 1.610 + 1.611 +#pragma pack() 1.612 + 1.613 +// Return just the highest bit of the given value, i.e., the highest 1.614 +// power of 2 that is <= value, or zero if the input value is zero. 1.615 +inline uint32_t 1.616 +FindHighestBit(uint32_t value) 1.617 +{ 1.618 + // propagate highest bit into all lower bits of the value 1.619 + value |= (value >> 1); 1.620 + value |= (value >> 2); 1.621 + value |= (value >> 4); 1.622 + value |= (value >> 8); 1.623 + value |= (value >> 16); 1.624 + // isolate the leftmost bit 1.625 + return (value & ~(value >> 1)); 1.626 +} 1.627 + 1.628 +} // namespace mozilla 1.629 + 1.630 +// used for overlaying name changes without touching original font data 1.631 +struct FontDataOverlay { 1.632 + // overlaySrc != 0 ==> use overlay 1.633 + uint32_t overlaySrc; // src offset from start of font data 1.634 + uint32_t overlaySrcLen; // src length 1.635 + uint32_t overlayDest; // dest offset from start of font data 1.636 +}; 1.637 + 1.638 +enum gfxUserFontType { 1.639 + GFX_USERFONT_UNKNOWN = 0, 1.640 + GFX_USERFONT_OPENTYPE = 1, 1.641 + GFX_USERFONT_SVG = 2, 1.642 + GFX_USERFONT_WOFF = 3 1.643 +}; 1.644 + 1.645 +extern const uint8_t sCJKCompatSVSTable[]; 1.646 + 1.647 +class gfxFontUtils { 1.648 + 1.649 +public: 1.650 + // these are public because gfxFont.cpp also looks into the name table 1.651 + enum { 1.652 + NAME_ID_FAMILY = 1, 1.653 + NAME_ID_STYLE = 2, 1.654 + NAME_ID_UNIQUE = 3, 1.655 + NAME_ID_FULL = 4, 1.656 + NAME_ID_VERSION = 5, 1.657 + NAME_ID_POSTSCRIPT = 6, 1.658 + NAME_ID_PREFERRED_FAMILY = 16, 1.659 + NAME_ID_PREFERRED_STYLE = 17, 1.660 + 1.661 + PLATFORM_ALL = -1, 1.662 + PLATFORM_ID_UNICODE = 0, // Mac OS uses this typically 1.663 + PLATFORM_ID_MAC = 1, 1.664 + PLATFORM_ID_ISO = 2, 1.665 + PLATFORM_ID_MICROSOFT = 3, 1.666 + 1.667 + ENCODING_ID_MAC_ROMAN = 0, // traditional Mac OS script manager encodings 1.668 + ENCODING_ID_MAC_JAPANESE = 1, // (there are others defined, but some were never 1.669 + ENCODING_ID_MAC_TRAD_CHINESE = 2, // implemented by Apple, and I have never seen them 1.670 + ENCODING_ID_MAC_KOREAN = 3, // used in font names) 1.671 + ENCODING_ID_MAC_ARABIC = 4, 1.672 + ENCODING_ID_MAC_HEBREW = 5, 1.673 + ENCODING_ID_MAC_GREEK = 6, 1.674 + ENCODING_ID_MAC_CYRILLIC = 7, 1.675 + ENCODING_ID_MAC_DEVANAGARI = 9, 1.676 + ENCODING_ID_MAC_GURMUKHI = 10, 1.677 + ENCODING_ID_MAC_GUJARATI = 11, 1.678 + ENCODING_ID_MAC_SIMP_CHINESE = 25, 1.679 + 1.680 + ENCODING_ID_MICROSOFT_SYMBOL = 0, // Microsoft platform encoding IDs 1.681 + ENCODING_ID_MICROSOFT_UNICODEBMP = 1, 1.682 + ENCODING_ID_MICROSOFT_SHIFTJIS = 2, 1.683 + ENCODING_ID_MICROSOFT_PRC = 3, 1.684 + ENCODING_ID_MICROSOFT_BIG5 = 4, 1.685 + ENCODING_ID_MICROSOFT_WANSUNG = 5, 1.686 + ENCODING_ID_MICROSOFT_JOHAB = 6, 1.687 + ENCODING_ID_MICROSOFT_UNICODEFULL = 10, 1.688 + 1.689 + LANG_ALL = -1, 1.690 + LANG_ID_MAC_ENGLISH = 0, // many others are defined, but most don't affect 1.691 + LANG_ID_MAC_HEBREW = 10, // the charset; should check all the central/eastern 1.692 + LANG_ID_MAC_JAPANESE = 11, // european codes, though 1.693 + LANG_ID_MAC_ARABIC = 12, 1.694 + LANG_ID_MAC_ICELANDIC = 15, 1.695 + LANG_ID_MAC_TURKISH = 17, 1.696 + LANG_ID_MAC_TRAD_CHINESE = 19, 1.697 + LANG_ID_MAC_URDU = 20, 1.698 + LANG_ID_MAC_KOREAN = 23, 1.699 + LANG_ID_MAC_POLISH = 25, 1.700 + LANG_ID_MAC_FARSI = 31, 1.701 + LANG_ID_MAC_SIMP_CHINESE = 33, 1.702 + LANG_ID_MAC_ROMANIAN = 37, 1.703 + LANG_ID_MAC_CZECH = 38, 1.704 + LANG_ID_MAC_SLOVAK = 39, 1.705 + 1.706 + LANG_ID_MICROSOFT_EN_US = 0x0409, // with Microsoft platformID, EN US lang code 1.707 + 1.708 + CMAP_MAX_CODEPOINT = 0x10ffff // maximum possible Unicode codepoint 1.709 + // contained in a cmap 1.710 + }; 1.711 + 1.712 + // name table has a header, followed by name records, followed by string data 1.713 + struct NameHeader { 1.714 + mozilla::AutoSwap_PRUint16 format; // Format selector (=0). 1.715 + mozilla::AutoSwap_PRUint16 count; // Number of name records. 1.716 + mozilla::AutoSwap_PRUint16 stringOffset; // Offset to start of string storage 1.717 + // (from start of table) 1.718 + }; 1.719 + 1.720 + struct NameRecord { 1.721 + mozilla::AutoSwap_PRUint16 platformID; // Platform ID 1.722 + mozilla::AutoSwap_PRUint16 encodingID; // Platform-specific encoding ID 1.723 + mozilla::AutoSwap_PRUint16 languageID; // Language ID 1.724 + mozilla::AutoSwap_PRUint16 nameID; // Name ID. 1.725 + mozilla::AutoSwap_PRUint16 length; // String length (in bytes). 1.726 + mozilla::AutoSwap_PRUint16 offset; // String offset from start of storage 1.727 + // (in bytes). 1.728 + }; 1.729 + 1.730 + // for reading big-endian font data on either big or little-endian platforms 1.731 + 1.732 + static inline uint16_t 1.733 + ReadShortAt(const uint8_t *aBuf, uint32_t aIndex) 1.734 + { 1.735 + return (aBuf[aIndex] << 8) | aBuf[aIndex + 1]; 1.736 + } 1.737 + 1.738 + static inline uint16_t 1.739 + ReadShortAt16(const uint16_t *aBuf, uint32_t aIndex) 1.740 + { 1.741 + const uint8_t *buf = reinterpret_cast<const uint8_t*>(aBuf); 1.742 + uint32_t index = aIndex << 1; 1.743 + return (buf[index] << 8) | buf[index+1]; 1.744 + } 1.745 + 1.746 + static inline uint32_t 1.747 + ReadUint24At(const uint8_t *aBuf, uint32_t aIndex) 1.748 + { 1.749 + return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) | 1.750 + (aBuf[aIndex + 2])); 1.751 + } 1.752 + 1.753 + static inline uint32_t 1.754 + ReadLongAt(const uint8_t *aBuf, uint32_t aIndex) 1.755 + { 1.756 + return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) | 1.757 + (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3])); 1.758 + } 1.759 + 1.760 + static nsresult 1.761 + ReadCMAPTableFormat12(const uint8_t *aBuf, uint32_t aLength, 1.762 + gfxSparseBitSet& aCharacterMap); 1.763 + 1.764 + static nsresult 1.765 + ReadCMAPTableFormat4(const uint8_t *aBuf, uint32_t aLength, 1.766 + gfxSparseBitSet& aCharacterMap); 1.767 + 1.768 + static nsresult 1.769 + ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength, 1.770 + uint8_t*& aTable); 1.771 + 1.772 + static uint32_t 1.773 + FindPreferredSubtable(const uint8_t *aBuf, uint32_t aBufLength, 1.774 + uint32_t *aTableOffset, uint32_t *aUVSTableOffset, 1.775 + bool *aSymbolEncoding); 1.776 + 1.777 + static nsresult 1.778 + ReadCMAP(const uint8_t *aBuf, uint32_t aBufLength, 1.779 + gfxSparseBitSet& aCharacterMap, 1.780 + uint32_t& aUVSOffset, 1.781 + bool& aUnicodeFont, bool& aSymbolFont); 1.782 + 1.783 + static uint32_t 1.784 + MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh); 1.785 + 1.786 + static uint32_t 1.787 + MapCharToGlyphFormat12(const uint8_t *aBuf, uint32_t aCh); 1.788 + 1.789 + static uint16_t 1.790 + MapUVSToGlyphFormat14(const uint8_t *aBuf, uint32_t aCh, uint32_t aVS); 1.791 + 1.792 + // sCJKCompatSVSTable is a 'cmap' format 14 subtable that maps 1.793 + // <char + var-selector> pairs to the corresponding Unicode 1.794 + // compatibility ideograph codepoints. 1.795 + static MOZ_ALWAYS_INLINE uint32_t 1.796 + GetUVSFallback(uint32_t aCh, uint32_t aVS) { 1.797 + aCh = MapUVSToGlyphFormat14(sCJKCompatSVSTable, aCh, aVS); 1.798 + return aCh >= 0xFB00 ? aCh + (0x2F800 - 0xFB00) : aCh; 1.799 + } 1.800 + 1.801 + static uint32_t 1.802 + MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, 1.803 + uint32_t aUnicode, uint32_t aVarSelector = 0); 1.804 + 1.805 +#ifdef XP_WIN 1.806 + // determine whether a font (which has already been sanitized, so is known 1.807 + // to be a valid sfnt) is CFF format rather than TrueType 1.808 + static bool 1.809 + IsCffFont(const uint8_t* aFontData); 1.810 +#endif 1.811 + 1.812 + // determine the format of font data 1.813 + static gfxUserFontType 1.814 + DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontDataLength); 1.815 + 1.816 + // Read the fullname from the sfnt data (used to save the original name 1.817 + // prior to renaming the font for installation). 1.818 + // This is called with sfnt data that has already been validated, 1.819 + // so it should always succeed in finding the name table. 1.820 + static nsresult 1.821 + GetFullNameFromSFNT(const uint8_t* aFontData, uint32_t aLength, 1.822 + nsAString& aFullName); 1.823 + 1.824 + // helper to get fullname from name table, constructing from family+style 1.825 + // if no explicit fullname is present 1.826 + static nsresult 1.827 + GetFullNameFromTable(hb_blob_t *aNameTable, 1.828 + nsAString& aFullName); 1.829 + 1.830 + // helper to get family name from name table 1.831 + static nsresult 1.832 + GetFamilyNameFromTable(hb_blob_t *aNameTable, 1.833 + nsAString& aFamilyName); 1.834 + 1.835 + // create a new name table and build a new font with that name table 1.836 + // appended on the end, returns true on success 1.837 + static nsresult 1.838 + RenameFont(const nsAString& aName, const uint8_t *aFontData, 1.839 + uint32_t aFontDataLength, FallibleTArray<uint8_t> *aNewFont); 1.840 + 1.841 + // read all names matching aNameID, returning in aNames array 1.842 + static nsresult 1.843 + ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID, 1.844 + int32_t aPlatformID, nsTArray<nsString>& aNames); 1.845 + 1.846 + // reads English or first name matching aNameID, returning in aName 1.847 + // platform based on OS 1.848 + static nsresult 1.849 + ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID, 1.850 + nsString& aName); 1.851 + 1.852 + static nsresult 1.853 + ReadCanonicalName(const char *aNameData, uint32_t aDataLen, 1.854 + uint32_t aNameID, nsString& aName); 1.855 + 1.856 + // convert a name from the raw name table data into an nsString, 1.857 + // provided we know how; return true if successful, or false 1.858 + // if we can't handle the encoding 1.859 + static bool 1.860 + DecodeFontName(const char *aBuf, int32_t aLength, 1.861 + uint32_t aPlatformCode, uint32_t aScriptCode, 1.862 + uint32_t aLangCode, nsAString& dest); 1.863 + 1.864 + static inline bool IsJoinCauser(uint32_t ch) { 1.865 + return (ch == 0x200D); 1.866 + } 1.867 + 1.868 + static inline bool IsJoinControl(uint32_t ch) { 1.869 + return (ch == 0x200C || ch == 0x200D); 1.870 + } 1.871 + 1.872 + enum { 1.873 + kUnicodeVS1 = 0xFE00, 1.874 + kUnicodeVS16 = 0xFE0F, 1.875 + kUnicodeVS17 = 0xE0100, 1.876 + kUnicodeVS256 = 0xE01EF 1.877 + }; 1.878 + 1.879 + static inline bool IsVarSelector(uint32_t ch) { 1.880 + return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) || 1.881 + (ch >= kUnicodeVS17 && ch <= kUnicodeVS256); 1.882 + } 1.883 + 1.884 + static inline bool IsInvalid(uint32_t ch) { 1.885 + return (ch == 0xFFFD); 1.886 + } 1.887 + 1.888 + // Font code may want to know if there is the potential for bidi behavior 1.889 + // to be triggered by any of the characters in a text run; this can be 1.890 + // used to test that possibility. 1.891 + enum { 1.892 + kUnicodeBidiScriptsStart = 0x0590, 1.893 + kUnicodeBidiScriptsEnd = 0x08FF, 1.894 + kUnicodeBidiPresentationStart = 0xFB1D, 1.895 + kUnicodeBidiPresentationEnd = 0xFEFC, 1.896 + kUnicodeFirstHighSurrogateBlock = 0xD800, 1.897 + kUnicodeRLM = 0x200F, 1.898 + kUnicodeRLE = 0x202B, 1.899 + kUnicodeRLO = 0x202E 1.900 + }; 1.901 + 1.902 + static inline bool PotentialRTLChar(char16_t aCh) { 1.903 + if (aCh >= kUnicodeBidiScriptsStart && aCh <= kUnicodeBidiScriptsEnd) 1.904 + // bidi scripts Hebrew, Arabic, Syriac, Thaana, N'Ko are all encoded together 1.905 + return true; 1.906 + 1.907 + if (aCh == kUnicodeRLM || aCh == kUnicodeRLE || aCh == kUnicodeRLO) 1.908 + // directional controls that trigger bidi layout 1.909 + return true; 1.910 + 1.911 + if (aCh >= kUnicodeBidiPresentationStart && 1.912 + aCh <= kUnicodeBidiPresentationEnd) 1.913 + // presentation forms of Arabic and Hebrew letters 1.914 + return true; 1.915 + 1.916 + if ((aCh & 0xFF00) == kUnicodeFirstHighSurrogateBlock) 1.917 + // surrogate that could be part of a bidi supplementary char 1.918 + // (Cypriot, Aramaic, Phoenecian, etc) 1.919 + return true; 1.920 + 1.921 + // otherwise we know this char cannot trigger bidi reordering 1.922 + return false; 1.923 + } 1.924 + 1.925 + // for a given font list pref name, set up a list of font names 1.926 + static void GetPrefsFontList(const char *aPrefName, 1.927 + nsTArray<nsString>& aFontList); 1.928 + 1.929 + // generate a unique font name 1.930 + static nsresult MakeUniqueUserFontName(nsAString& aName); 1.931 + 1.932 +protected: 1.933 + static nsresult 1.934 + ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID, 1.935 + int32_t aLangID, int32_t aPlatformID, nsTArray<nsString>& aNames); 1.936 + 1.937 + // convert opentype name-table platform/encoding/language values to a charset name 1.938 + // we can use to convert the name data to unicode, or "" if data is UTF16BE 1.939 + static const char* 1.940 + GetCharsetForFontName(uint16_t aPlatform, uint16_t aScript, uint16_t aLanguage); 1.941 + 1.942 + struct MacFontNameCharsetMapping { 1.943 + uint16_t mEncoding; 1.944 + uint16_t mLanguage; 1.945 + const char *mCharsetName; 1.946 + 1.947 + bool operator<(const MacFontNameCharsetMapping& rhs) const { 1.948 + return (mEncoding < rhs.mEncoding) || 1.949 + ((mEncoding == rhs.mEncoding) && (mLanguage < rhs.mLanguage)); 1.950 + } 1.951 + }; 1.952 + static const MacFontNameCharsetMapping gMacFontNameCharsets[]; 1.953 + static const char* gISOFontNameCharsets[]; 1.954 + static const char* gMSFontNameCharsets[]; 1.955 +}; 1.956 + 1.957 + 1.958 +#endif /* GFX_FONT_UTILS_H */