gfx/thebes/gfxFontUtils.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #ifndef GFX_FONT_UTILS_H
     7 #define GFX_FONT_UTILS_H
     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"
    17 #include "zlib.h"
    18 #include <algorithm>
    20 /* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
    21 #ifdef __MINGW32__
    22 #undef min
    23 #undef max
    24 #endif
    26 typedef struct hb_blob_t hb_blob_t;
    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 };
    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     };
    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     }
    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     }
    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     }
    84 #if PR_LOGGING
    85     // dump out contents of bitmap
    86     void Dump(const char* aPrefix, eGfxLog aWhichLog) const;
    87 #endif
    89     bool TestRange(uint32_t aStart, uint32_t aEnd) {
    90         uint32_t startBlock, endBlock, blockLen;
    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;
    97         // check for blocks in range, if none, return false
    98         uint32_t blockIndex;
    99         bool hasBlocksInRange = false;
   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;
   109         Block *block;
   110         uint32_t i, start, end;
   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;
   123         // [2..n-1] blocks check bytes
   124         for (blockIndex = startBlock + 1; blockIndex < endBlock; blockIndex++) {
   125             uint32_t index;
   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         }
   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         }
   144         return false;
   145     }
   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     }
   162     void set(uint32_t aIndex, bool aValue) {
   163         if (aValue)
   164             set(aIndex);
   165         else
   166             clear(aIndex);
   167     }
   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;
   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         }
   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;
   184             Block *block = mBlocks[i];
   185             if (!block) {
   186                 bool fullBlock = false;
   187                 if (aStart <= blockFirstBit && aEnd >= blockLastBit)
   188                     fullBlock = true;
   190                 block = new Block(fullBlock ? 0xFF : 0);
   191                 mBlocks[i] = block;
   193                 if (fullBlock)
   194                     continue;
   195             }
   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);
   200             for (uint32_t bit = start; bit <= end; ++bit) {
   201                 block->mBits[bit>>3] |= 1 << (bit & 0x7);
   202             }
   203         }
   204     }
   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     }
   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;
   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         }
   231         for (uint32_t i = startIndex; i <= endIndex; ++i) {
   232             const uint32_t blockFirstBit = i * BLOCK_SIZE_BITS;
   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             }
   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);
   244             for (uint32_t bit = start; bit <= end; ++bit) {
   245                 block->mBits[bit>>3] &= ~(1 << (bit & 0x7));
   246             }
   247         }
   248     }
   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     }
   260     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
   261         return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   262     }
   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     }
   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     }
   303     void Compact() {
   304         mBlocks.Compact();
   305     }
   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     }
   319 private:
   320     nsTArray< nsAutoPtr<Block> > mBlocks;
   321 };
   323 #define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
   325 namespace mozilla {
   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)
   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     }
   349     operator uint32_t() const
   350     {
   351         return mozilla::NativeEndian::swapFromBigEndian(value);
   352     }
   354     operator uint64_t() const
   355     {
   356         return mozilla::NativeEndian::swapFromBigEndian(value);
   357     }
   359 private:
   360     uint16_t value;
   361 };
   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     }
   381     operator uint32_t() const
   382     {
   383         return mozilla::NativeEndian::swapFromBigEndian(value);
   384     }
   386 private:
   387     int16_t  value;
   388 };
   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     }
   408 private:
   409     uint32_t  value;
   410 };
   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     }
   430 private:
   431     int32_t  value;
   432 };
   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     }
   452 private:
   453     uint64_t  value;
   454 };
   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 };
   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 };
   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 };
   478 struct HeadTable {
   479     enum {
   480         HEAD_VERSION = 0x00010000,
   481         HEAD_MAGIC_NUMBER = 0x5F0F3CF5,
   482         HEAD_CHECKSUM_CALC_CONST = 0xB1B0AFBA
   483     };
   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 };
   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 };
   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 };
   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 };
   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 };
   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 };
   589 struct KernTableSubtableHeaderVersion0 {
   590     AutoSwap_PRUint16    version;
   591     AutoSwap_PRUint16    length;
   592     AutoSwap_PRUint16    coverage;
   593 };
   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 };
   602 struct KernTableSubtableHeaderVersion1 {
   603     AutoSwap_PRUint32    length;
   604     AutoSwap_PRUint16    coverage;
   605     AutoSwap_PRUint16    tupleIndex;
   606 };
   608 #pragma pack()
   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 }
   625 } // namespace mozilla
   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 };
   635 enum gfxUserFontType {
   636     GFX_USERFONT_UNKNOWN = 0,
   637     GFX_USERFONT_OPENTYPE = 1,
   638     GFX_USERFONT_SVG = 2,
   639     GFX_USERFONT_WOFF = 3
   640 };
   642 extern const uint8_t sCJKCompatSVSTable[];
   644 class gfxFontUtils {
   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,
   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,
   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,
   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,
   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,
   703         LANG_ID_MICROSOFT_EN_US = 0x0409,        // with Microsoft platformID, EN US lang code
   705         CMAP_MAX_CODEPOINT = 0x10ffff     // maximum possible Unicode codepoint 
   706                                           // contained in a cmap
   707     };
   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     };
   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     };
   727     // for reading big-endian font data on either big or little-endian platforms
   729     static inline uint16_t
   730     ReadShortAt(const uint8_t *aBuf, uint32_t aIndex)
   731     {
   732         return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
   733     }
   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     }
   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     }
   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     }
   757     static nsresult
   758     ReadCMAPTableFormat12(const uint8_t *aBuf, uint32_t aLength, 
   759                           gfxSparseBitSet& aCharacterMap);
   761     static nsresult 
   762     ReadCMAPTableFormat4(const uint8_t *aBuf, uint32_t aLength, 
   763                          gfxSparseBitSet& aCharacterMap);
   765     static nsresult
   766     ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength, 
   767                           uint8_t*& aTable);
   769     static uint32_t
   770     FindPreferredSubtable(const uint8_t *aBuf, uint32_t aBufLength,
   771                           uint32_t *aTableOffset, uint32_t *aUVSTableOffset,
   772                           bool *aSymbolEncoding);
   774     static nsresult
   775     ReadCMAP(const uint8_t *aBuf, uint32_t aBufLength,
   776              gfxSparseBitSet& aCharacterMap,
   777              uint32_t& aUVSOffset,
   778              bool& aUnicodeFont, bool& aSymbolFont);
   780     static uint32_t
   781     MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh);
   783     static uint32_t
   784     MapCharToGlyphFormat12(const uint8_t *aBuf, uint32_t aCh);
   786     static uint16_t
   787     MapUVSToGlyphFormat14(const uint8_t *aBuf, uint32_t aCh, uint32_t aVS);
   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     }
   798     static uint32_t
   799     MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength,
   800                    uint32_t aUnicode, uint32_t aVarSelector = 0);
   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
   809     // determine the format of font data
   810     static gfxUserFontType
   811     DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontDataLength);
   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);
   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);
   827     // helper to get family name from name table
   828     static nsresult
   829     GetFamilyNameFromTable(hb_blob_t *aNameTable,
   830                            nsAString& aFamilyName);
   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);
   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);
   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);
   849     static nsresult
   850     ReadCanonicalName(const char *aNameData, uint32_t aDataLen,
   851                       uint32_t aNameID, nsString& aName);
   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);
   861     static inline bool IsJoinCauser(uint32_t ch) {
   862         return (ch == 0x200D);
   863     }
   865     static inline bool IsJoinControl(uint32_t ch) {
   866         return (ch == 0x200C || ch == 0x200D);
   867     }
   869     enum {
   870         kUnicodeVS1 = 0xFE00,
   871         kUnicodeVS16 = 0xFE0F,
   872         kUnicodeVS17 = 0xE0100,
   873         kUnicodeVS256 = 0xE01EF
   874     };
   876     static inline bool IsVarSelector(uint32_t ch) {
   877         return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
   878                (ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
   879     }
   881     static inline bool IsInvalid(uint32_t ch) {
   882         return (ch == 0xFFFD);
   883     }
   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     };
   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;
   904         if (aCh == kUnicodeRLM || aCh == kUnicodeRLE || aCh == kUnicodeRLO)
   905             // directional controls that trigger bidi layout
   906             return true;
   908         if (aCh >= kUnicodeBidiPresentationStart &&
   909             aCh <= kUnicodeBidiPresentationEnd)
   910             // presentation forms of Arabic and Hebrew letters
   911             return true;
   913         if ((aCh & 0xFF00) == kUnicodeFirstHighSurrogateBlock)
   914             // surrogate that could be part of a bidi supplementary char
   915             // (Cypriot, Aramaic, Phoenecian, etc)
   916             return true;
   918         // otherwise we know this char cannot trigger bidi reordering
   919         return false;
   920     }
   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);
   926     // generate a unique font name
   927     static nsresult MakeUniqueUserFontName(nsAString& aName);
   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);
   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);
   939     struct MacFontNameCharsetMapping {
   940         uint16_t    mEncoding;
   941         uint16_t    mLanguage;
   942         const char *mCharsetName;
   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 };
   955 #endif /* GFX_FONT_UTILS_H */

mercurial