LCOV - app.info - gfx/thebes/gfxFontUtils.h

LCOV - code coverage report
| Current view: | directory - gfx/thebes - gfxFontUtils.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 118 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 31 | 0 | 0.0 %

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

Generated by: LCOV version 1.7