LCOV - code coverage report
Current view: directory - objdir/dist/include - gfxFontUtils.h (source / functions) Found Hit Coverage
Test: app.info Lines: 13 0 0.0 %
Date: 2012-06-02 Functions: 2 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                 : 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                 :         Block(const Block& aBlock) { memcpy(mBits, aBlock.mBits, sizeof(mBits)); }
      75                 :         Block(unsigned char memsetValue = 0) { memset(mBits, memsetValue, BLOCK_SIZE); }
      76                 :         PRUint8 mBits[BLOCK_SIZE];
      77                 :     };
      78                 : 
      79                 : public:
      80                 :     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                 :     void set(PRUint32 aIndex) {
     165                 :         PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
     166                 :         if (blockIndex >= mBlocks.Length()) {
     167                 :             nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
     168                 :             if (NS_UNLIKELY(!blocks)) // OOM
     169                 :                 return;
     170                 :         }
     171                 :         Block *block = mBlocks[blockIndex];
     172                 :         if (!block) {
     173                 :             block = new Block;
     174                 :             mBlocks[blockIndex] = block;
     175                 :         }
     176                 :         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                 :     void SetRange(PRUint32 aStart, PRUint32 aEnd) {
     187                 :         const PRUint32 startIndex = aStart/BLOCK_SIZE_BITS;
     188                 :         const PRUint32 endIndex = aEnd/BLOCK_SIZE_BITS;
     189                 : 
     190                 :         if (endIndex >= mBlocks.Length()) {
     191                 :             PRUint32 numNewBlocks = endIndex + 1 - mBlocks.Length();
     192                 :             nsAutoPtr<Block> *blocks = mBlocks.AppendElements(numNewBlocks);
     193                 :             if (NS_UNLIKELY(!blocks)) // OOM
     194                 :                 return;
     195                 :         }
     196                 : 
     197                 :         for (PRUint32 i = startIndex; i <= endIndex; ++i) {
     198                 :             const PRUint32 blockFirstBit = i * BLOCK_SIZE_BITS;
     199                 :             const PRUint32 blockLastBit = blockFirstBit + BLOCK_SIZE_BITS - 1;
     200                 : 
     201                 :             Block *block = mBlocks[i];
     202                 :             if (!block) {
     203                 :                 bool fullBlock = false;
     204                 :                 if (aStart <= blockFirstBit && aEnd >= blockLastBit)
     205                 :                     fullBlock = true;
     206                 : 
     207                 :                 block = new Block(fullBlock ? 0xFF : 0);
     208                 :                 mBlocks[i] = block;
     209                 : 
     210                 :                 if (fullBlock)
     211                 :                     continue;
     212                 :             }
     213                 : 
     214                 :             const PRUint32 start = aStart > blockFirstBit ? aStart - blockFirstBit : 0;
     215                 :             const PRUint32 end = NS_MIN<PRUint32>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
     216                 : 
     217                 :             for (PRUint32 bit = start; bit <= end; ++bit) {
     218                 :                 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                 :     void Union(const gfxSparseBitSet& aBitset) {
     286                 :         // ensure mBlocks is large enough
     287                 :         PRUint32 blockCount = aBitset.mBlocks.Length();
     288                 :         if (blockCount > mBlocks.Length()) {
     289                 :             PRUint32 needed = blockCount - mBlocks.Length();
     290                 :             nsAutoPtr<Block> *blocks = mBlocks.AppendElements(needed);
     291                 :             if (NS_UNLIKELY(!blocks)) { // OOM
     292                 :                 return;
     293                 :             }
     294                 :         }
     295                 :         // for each block that may be present in aBitset...
     296                 :         for (PRUint32 i = 0; i < blockCount; ++i) {
     297                 :             // if it is missing (implicitly empty), just skip
     298                 :             if (!aBitset.mBlocks[i]) {
     299                 :                 continue;
     300                 :             }
     301                 :             // if the block is missing in this set, just copy the other
     302                 :             if (!mBlocks[i]) {
     303                 :                 mBlocks[i] = new Block(*aBitset.mBlocks[i]);
     304                 :                 continue;
     305                 :             }
     306                 :             // else set existing block to the union of both
     307                 :             PRUint32 *dst = reinterpret_cast<PRUint32*>(mBlocks[i]->mBits);
     308                 :             const PRUint32 *src =
     309                 :                 reinterpret_cast<const PRUint32*>(aBitset.mBlocks[i]->mBits);
     310                 :             for (PRUint32 j = 0; j < BLOCK_SIZE / 4; ++j) {
     311                 :                 dst[j] |= src[j];
     312                 :             }
     313                 :         }
     314                 :     }
     315                 : 
     316                 :     void Compact() {
     317                 :         mBlocks.Compact();
     318                 :     }
     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                 :     AutoSwap_PRUint16(PRUint16 aValue) { value = NS_SWAP16(aValue); }
     338                 : #endif
     339                 :     operator PRUint16() const { return NS_SWAP16(value); }
     340                 :     operator PRUint32() const { return NS_SWAP16(value); }
     341                 :     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                 :     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                 :     AutoSwap_PRUint32(PRUint32 aValue) { value = NS_SWAP32(aValue); }
     363                 : #endif
     364                 :     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                 :     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                 : FindHighestBit(PRUint32 value)
     548                 : {
     549                 :     // propagate highest bit into all lower bits of the value
     550                 :     value |= (value >> 1);
     551                 :     value |= (value >> 2);
     552                 :     value |= (value >> 4);
     553                 :     value |= (value >> 8);
     554                 :     value |= (value >> 16);
     555                 :     // isolate the leftmost bit
     556                 :     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                 :     ReadShortAt(const PRUint8 *aBuf, PRUint32 aIndex)
     663                 :     {
     664                 :         return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
     665                 :     }
     666                 : 
     667                 :     static inline PRUint16
     668                 :     ReadShortAt16(const PRUint16 *aBuf, PRUint32 aIndex)
     669                 :     {
     670                 :         const PRUint8 *buf = reinterpret_cast<const PRUint8*>(aBuf);
     671                 :         PRUint32 index = aIndex << 1;
     672                 :         return (buf[index] << 8) | buf[index+1];
     673                 :     }
     674                 : 
     675                 :     static inline PRUint32
     676                 :     ReadUint24At(const PRUint8 *aBuf, PRUint32 aIndex)
     677                 :     {
     678                 :         return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) |
     679                 :                 (aBuf[aIndex + 2]));
     680                 :     }
     681                 : 
     682                 :     static inline PRUint32
     683                 :     ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
     684                 :     {
     685                 :         return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) | 
     686                 :                 (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                 :     static inline bool IsJoinCauser(PRUint32 ch) {
     793                 :         return (ch == 0x200D);
     794                 :     }
     795                 : 
     796                 :     static inline bool IsJoinControl(PRUint32 ch) {
     797                 :         return (ch == 0x200C || ch == 0x200D);
     798                 :     }
     799                 : 
     800                 :     enum {
     801                 :         kUnicodeVS1 = 0xFE00,
     802                 :         kUnicodeVS16 = 0xFE0F,
     803                 :         kUnicodeVS17 = 0xE0100,
     804                 :         kUnicodeVS256 = 0xE01EF
     805                 :     };
     806                 : 
     807                 :     static inline bool IsVarSelector(PRUint32 ch) {
     808                 :         return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
     809                 :                (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                 :         bool operator<(const MacFontNameCharsetMapping& rhs) const {
     878                 :             return (mEncoding < rhs.mEncoding) ||
     879                 :                    ((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                 :     gfxFontInfoLoader() :
     908                 :         mInterval(0), mState(stateInitial)
     909                 :     {
     910                 :     }
     911                 : 
     912                 :     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                 :     void CancelLoader() {
     951                 :         if (mState == stateInitial)
     952                 :             return;
     953                 :         mState = stateTimerOff;
     954                 :         if (mTimer) {
     955                 :             mTimer->Cancel();
     956                 :         }
     957                 :         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