LCOV - code coverage report
Current view: directory - gfx/thebes - gfxFont.h (source / functions) Found Hit Coverage
Test: app.info Lines: 529 0 0.0 %
Date: 2012-06-02 Functions: 202 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                 :  *   Masayuki Nakano <masayuki@d-toybox.com>
      24                 :  *   John Daggett <jdaggett@mozilla.com>
      25                 :  *   Jonathan Kew <jfkthame@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #ifndef GFX_FONT_H
      42                 : #define GFX_FONT_H
      43                 : 
      44                 : #include "prtypes.h"
      45                 : #include "nsAlgorithm.h"
      46                 : #include "gfxTypes.h"
      47                 : #include "nsString.h"
      48                 : #include "gfxPoint.h"
      49                 : #include "gfxFontUtils.h"
      50                 : #include "nsTArray.h"
      51                 : #include "nsTHashtable.h"
      52                 : #include "nsHashKeys.h"
      53                 : #include "gfxSkipChars.h"
      54                 : #include "gfxRect.h"
      55                 : #include "nsExpirationTracker.h"
      56                 : #include "gfxFontConstants.h"
      57                 : #include "gfxPlatform.h"
      58                 : #include "nsIAtom.h"
      59                 : #include "nsISupportsImpl.h"
      60                 : #include "gfxPattern.h"
      61                 : #include "mozilla/HashFunctions.h"
      62                 : 
      63                 : typedef struct _cairo_scaled_font cairo_scaled_font_t;
      64                 : 
      65                 : #ifdef DEBUG
      66                 : #include <stdio.h>
      67                 : #endif
      68                 : 
      69                 : class gfxContext;
      70                 : class gfxTextRun;
      71                 : class gfxFont;
      72                 : class gfxFontFamily;
      73                 : class gfxFontGroup;
      74                 : class gfxUserFontSet;
      75                 : class gfxUserFontData;
      76                 : class gfxShapedWord;
      77                 : 
      78                 : class nsILanguageAtomService;
      79                 : 
      80                 : typedef struct _hb_blob_t hb_blob_t;
      81                 : 
      82                 : // We should eliminate these synonyms when it won't cause many merge conflicts.
      83                 : #define FONT_STYLE_NORMAL              NS_FONT_STYLE_NORMAL
      84                 : #define FONT_STYLE_ITALIC              NS_FONT_STYLE_ITALIC
      85                 : #define FONT_STYLE_OBLIQUE             NS_FONT_STYLE_OBLIQUE
      86                 : 
      87                 : // We should eliminate these synonyms when it won't cause many merge conflicts.
      88                 : #define FONT_WEIGHT_NORMAL             NS_FONT_WEIGHT_NORMAL
      89                 : #define FONT_WEIGHT_BOLD               NS_FONT_WEIGHT_BOLD
      90                 : 
      91                 : #define FONT_MAX_SIZE                  2000.0
      92                 : 
      93                 : #define NO_FONT_LANGUAGE_OVERRIDE      0
      94                 : 
      95                 : // An OpenType feature tag and value pair
      96               0 : struct THEBES_API gfxFontFeature {
      97                 :     PRUint32 mTag; // see http://www.microsoft.com/typography/otspec/featuretags.htm
      98                 :     PRUint32 mValue; // 0 = off, 1 = on, larger values may be used as parameters
      99                 :                      // to features that select among multiple alternatives
     100                 : };
     101                 : 
     102                 : inline bool
     103               0 : operator<(const gfxFontFeature& a, const gfxFontFeature& b)
     104                 : {
     105               0 :     return (a.mTag < b.mTag) || ((a.mTag == b.mTag) && (a.mValue < b.mValue));
     106                 : }
     107                 : 
     108                 : inline bool
     109               0 : operator==(const gfxFontFeature& a, const gfxFontFeature& b)
     110                 : {
     111               0 :     return (a.mTag == b.mTag) && (a.mValue == b.mValue);
     112                 : }
     113                 : 
     114                 : 
     115               0 : struct THEBES_API gfxFontStyle {
     116                 :     gfxFontStyle();
     117                 :     gfxFontStyle(PRUint8 aStyle, PRUint16 aWeight, PRInt16 aStretch,
     118                 :                  gfxFloat aSize, nsIAtom *aLanguage,
     119                 :                  float aSizeAdjust, bool aSystemFont,
     120                 :                  bool aPrinterFont,
     121                 :                  const nsString& aFeatureSettings,
     122                 :                  const nsString& aLanguageOverride);
     123                 :     gfxFontStyle(const gfxFontStyle& aStyle);
     124                 : 
     125                 :     // The style of font (normal, italic, oblique)
     126                 :     PRUint8 style : 7;
     127                 : 
     128                 :     // Say that this font is a system font and therefore does not
     129                 :     // require certain fixup that we do for fonts from untrusted
     130                 :     // sources.
     131                 :     bool systemFont : 1;
     132                 : 
     133                 :     // Say that this font is used for print or print preview.
     134                 :     bool printerFont : 1;
     135                 : 
     136                 :     // The weight of the font: 100, 200, ... 900.
     137                 :     PRUint16 weight;
     138                 : 
     139                 :     // The stretch of the font (the sum of various NS_FONT_STRETCH_*
     140                 :     // constants; see gfxFontConstants.h).
     141                 :     PRInt16 stretch;
     142                 : 
     143                 :     // The logical size of the font, in pixels
     144                 :     gfxFloat size;
     145                 : 
     146                 :     // The aspect-value (ie., the ratio actualsize:actualxheight) that any
     147                 :     // actual physical font created from this font structure must have when
     148                 :     // rendering or measuring a string. A value of 0 means no adjustment
     149                 :     // needs to be done.
     150                 :     float sizeAdjust;
     151                 : 
     152                 :     // the language (may be an internal langGroup code rather than an actual
     153                 :     // language code) specified in the document or element's lang property,
     154                 :     // or inferred from the charset
     155                 :     nsRefPtr<nsIAtom> language;
     156                 : 
     157                 :     // Language system tag, to override document language;
     158                 :     // an OpenType "language system" tag represented as a 32-bit integer
     159                 :     // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
     160                 :     // Normally 0, so font rendering will use the document or element language
     161                 :     // (see above) to control any language-specific rendering, but the author
     162                 :     // can override this for cases where the options implemented in the font
     163                 :     // do not directly match the actual language. (E.g. lang may be Macedonian,
     164                 :     // but the font in use does not explicitly support this; the author can
     165                 :     // use font-language-override to request the Serbian option in the font
     166                 :     // in order to get correct glyph shapes.)
     167                 :     PRUint32 languageOverride;
     168                 : 
     169                 :     // custom opentype feature settings
     170                 :     nsTArray<gfxFontFeature> featureSettings;
     171                 : 
     172                 :     // Return the final adjusted font size for the given aspect ratio.
     173                 :     // Not meant to be called when sizeAdjust = 0.
     174                 :     gfxFloat GetAdjustedSize(gfxFloat aspect) const {
     175                 :         NS_ASSERTION(sizeAdjust != 0.0, "Not meant to be called when sizeAdjust = 0");
     176                 :         gfxFloat adjustedSize = NS_MAX(NS_round(size*(sizeAdjust/aspect)), 1.0);
     177                 :         return NS_MIN(adjustedSize, FONT_MAX_SIZE);
     178                 :     }
     179                 : 
     180               0 :     PLDHashNumber Hash() const {
     181                 :         return ((style + (systemFont << 7) +
     182                 :             (weight << 8)) + PRUint32(size*1000) + PRUint32(sizeAdjust*1000)) ^
     183               0 :             nsISupportsHashKey::HashKey(language);
     184                 :     }
     185                 : 
     186                 :     PRInt8 ComputeWeight() const;
     187                 : 
     188               0 :     bool Equals(const gfxFontStyle& other) const {
     189                 :         return (size == other.size) &&
     190                 :             (style == other.style) &&
     191                 :             (systemFont == other.systemFont) &&
     192                 :             (printerFont == other.printerFont) &&
     193                 :             (weight == other.weight) &&
     194                 :             (stretch == other.stretch) &&
     195               0 :             (language == other.language) &&
     196                 :             (sizeAdjust == other.sizeAdjust) &&
     197               0 :             (featureSettings == other.featureSettings) &&
     198               0 :             (languageOverride == other.languageOverride);
     199                 :     }
     200                 : 
     201                 :     static void ParseFontFeatureSettings(const nsString& aFeatureString,
     202                 :                                          nsTArray<gfxFontFeature>& aFeatures);
     203                 : 
     204                 :     static PRUint32 ParseFontLanguageOverride(const nsString& aLangTag);
     205                 : };
     206                 : 
     207                 : class gfxFontEntry {
     208                 : public:
     209               0 :     NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
     210                 : 
     211               0 :     gfxFontEntry(const nsAString& aName, gfxFontFamily *aFamily = nsnull,
     212                 :                  bool aIsStandardFace = false) : 
     213                 :         mName(aName), mItalic(false), mFixedPitch(false),
     214                 :         mIsProxy(false), mIsValid(true), 
     215                 :         mIsBadUnderlineFont(false), mIsUserFont(false),
     216                 :         mIsLocalUserFont(false), mStandardFace(aIsStandardFace),
     217                 :         mSymbolFont(false),
     218                 :         mIgnoreGDEF(false),
     219                 :         mIgnoreGSUB(false),
     220                 :         mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
     221                 : #ifdef MOZ_GRAPHITE
     222                 :         mCheckedForGraphiteTables(false),
     223                 : #endif
     224                 :         mHasCmapTable(false),
     225                 :         mCmapInitialized(false),
     226                 :         mUVSOffset(0), mUVSData(nsnull),
     227                 :         mUserFontData(nsnull),
     228                 :         mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
     229               0 :         mFamily(aFamily)
     230               0 :     { }
     231                 : 
     232                 :     virtual ~gfxFontEntry();
     233                 : 
     234                 :     // unique name for the face, *not* the family; not necessarily the
     235                 :     // "real" or user-friendly name, may be an internal identifier
     236               0 :     const nsString& Name() const { return mName; }
     237                 : 
     238                 :     // the "real" name of the face, if available from the font resource
     239                 :     // (may be expensive); returns Name() if nothing better is available
     240                 :     virtual nsString RealFaceName();
     241                 : 
     242               0 :     gfxFontFamily* Family() const { return mFamily; }
     243                 : 
     244               0 :     PRUint16 Weight() const { return mWeight; }
     245               0 :     PRInt16 Stretch() const { return mStretch; }
     246                 : 
     247               0 :     bool IsUserFont() const { return mIsUserFont; }
     248                 :     bool IsLocalUserFont() const { return mIsLocalUserFont; }
     249               0 :     bool IsFixedPitch() const { return mFixedPitch; }
     250               0 :     bool IsItalic() const { return mItalic; }
     251               0 :     bool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
     252               0 :     bool IgnoreGDEF() const { return mIgnoreGDEF; }
     253               0 :     bool IgnoreGSUB() const { return mIgnoreGSUB; }
     254                 : 
     255                 :     virtual bool IsSymbolFont();
     256                 : 
     257                 : #ifdef MOZ_GRAPHITE
     258               0 :     inline bool HasGraphiteTables() {
     259               0 :         if (!mCheckedForGraphiteTables) {
     260               0 :             CheckForGraphiteTables();
     261               0 :             mCheckedForGraphiteTables = true;
     262                 :         }
     263               0 :         return mHasGraphiteTables;
     264                 :     }
     265                 : #endif
     266                 : 
     267               0 :     inline bool HasCmapTable() {
     268               0 :         if (!mCmapInitialized) {
     269               0 :             ReadCMAP();
     270                 :         }
     271               0 :         return mHasCmapTable;
     272                 :     }
     273                 : 
     274               0 :     inline bool HasCharacter(PRUint32 ch) {
     275               0 :         if (mCharacterMap.test(ch))
     276               0 :             return true;
     277                 : 
     278               0 :         return TestCharacterMap(ch);
     279                 :     }
     280                 : 
     281               0 :     virtual bool SkipDuringSystemFallback() { return false; }
     282                 :     virtual bool TestCharacterMap(PRUint32 aCh);
     283                 :     nsresult InitializeUVSMap();
     284                 :     PRUint16 GetUVSGlyph(PRUint32 aCh, PRUint32 aVS);
     285                 :     virtual nsresult ReadCMAP();
     286                 : 
     287               0 :     virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
     288               0 :         return true;
     289                 :     }
     290               0 :     virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
     291               0 :         return true;
     292                 :     }
     293                 : 
     294               0 :     virtual nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer) {
     295               0 :         return NS_ERROR_FAILURE; // all platform subclasses should reimplement this!
     296                 :     }
     297                 : 
     298               0 :     void SetFamily(gfxFontFamily* aFamily) {
     299               0 :         mFamily = aFamily;
     300               0 :     }
     301                 : 
     302                 :     virtual nsString FamilyName() const;
     303                 : 
     304                 :     already_AddRefed<gfxFont> FindOrMakeFont(const gfxFontStyle *aStyle,
     305                 :                                              bool aNeedsBold);
     306                 : 
     307                 :     // Get an existing font table cache entry in aBlob if it has been
     308                 :     // registered, or return false if not.  Callers must call
     309                 :     // hb_blob_destroy on aBlob if true is returned.
     310                 :     //
     311                 :     // Note that some gfxFont implementations may not call this at all,
     312                 :     // if it is more efficient to get the table from the OS at that level.
     313                 :     bool GetExistingFontTable(PRUint32 aTag, hb_blob_t** aBlob);
     314                 : 
     315                 :     // Elements of aTable are transferred (not copied) to and returned in a
     316                 :     // new hb_blob_t which is registered on the gfxFontEntry, but the initial
     317                 :     // reference is owned by the caller.  Removing the last reference
     318                 :     // unregisters the table from the font entry.
     319                 :     //
     320                 :     // Pass NULL for aBuffer to indicate that the table is not present and
     321                 :     // NULL will be returned.  Also returns NULL on OOM.
     322                 :     hb_blob_t *ShareFontTableAndGetBlob(PRUint32 aTag,
     323                 :                                         FallibleTArray<PRUint8>* aTable);
     324                 : 
     325                 :     nsString         mName;
     326                 : 
     327                 :     bool             mItalic      : 1;
     328                 :     bool             mFixedPitch  : 1;
     329                 :     bool             mIsProxy     : 1;
     330                 :     bool             mIsValid     : 1;
     331                 :     bool             mIsBadUnderlineFont : 1;
     332                 :     bool             mIsUserFont  : 1;
     333                 :     bool             mIsLocalUserFont  : 1;
     334                 :     bool             mStandardFace : 1;
     335                 :     bool             mSymbolFont  : 1;
     336                 :     bool             mIgnoreGDEF  : 1;
     337                 :     bool             mIgnoreGSUB  : 1;
     338                 : 
     339                 :     PRUint16         mWeight;
     340                 :     PRInt16          mStretch;
     341                 : 
     342                 : #ifdef MOZ_GRAPHITE
     343                 :     bool             mHasGraphiteTables;
     344                 :     bool             mCheckedForGraphiteTables;
     345                 : #endif
     346                 :     bool             mHasCmapTable;
     347                 :     bool             mCmapInitialized;
     348                 :     gfxSparseBitSet  mCharacterMap;
     349                 :     PRUint32         mUVSOffset;
     350                 :     nsAutoArrayPtr<PRUint8> mUVSData;
     351                 :     gfxUserFontData* mUserFontData;
     352                 : 
     353                 :     nsTArray<gfxFontFeature> mFeatureSettings;
     354                 :     PRUint32         mLanguageOverride;
     355                 : 
     356                 : protected:
     357                 :     friend class gfxPlatformFontList;
     358                 :     friend class gfxMacPlatformFontList;
     359                 :     friend class gfxUserFcFontEntry;
     360                 :     friend class gfxFontFamily;
     361                 :     friend class gfxSingleFaceMacFontFamily;
     362                 : 
     363                 :     gfxFontEntry() :
     364                 :         mItalic(false), mFixedPitch(false),
     365                 :         mIsProxy(false), mIsValid(true), 
     366                 :         mIsBadUnderlineFont(false),
     367                 :         mIsUserFont(false),
     368                 :         mIsLocalUserFont(false),
     369                 :         mStandardFace(false),
     370                 :         mSymbolFont(false),
     371                 :         mIgnoreGDEF(false),
     372                 :         mIgnoreGSUB(false),
     373                 :         mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
     374                 : #ifdef MOZ_GRAPHITE
     375                 :         mCheckedForGraphiteTables(false),
     376                 : #endif
     377                 :         mHasCmapTable(false),
     378                 :         mCmapInitialized(false),
     379                 :         mUVSOffset(0), mUVSData(nsnull),
     380                 :         mUserFontData(nsnull),
     381                 :         mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
     382                 :         mFamily(nsnull)
     383                 :     { }
     384                 : 
     385               0 :     virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) {
     386               0 :         NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
     387               0 :         return nsnull;
     388                 :     }
     389                 : 
     390                 : #ifdef MOZ_GRAPHITE
     391                 :     virtual void CheckForGraphiteTables();
     392                 : #endif
     393                 : 
     394                 :     gfxFontFamily *mFamily;
     395                 : 
     396                 : private:
     397                 : 
     398                 :     /**
     399                 :      * Font table hashtable, to support GetFontTable for harfbuzz.
     400                 :      *
     401                 :      * The harfbuzz shaper (and potentially other clients) needs access to raw
     402                 :      * font table data. This needs to be cached so that it can be used
     403                 :      * repeatedly (each time we construct a text run; in some cases, for
     404                 :      * each character/glyph within the run) without re-fetching large tables
     405                 :      * every time.
     406                 :      * 
     407                 :      * Because we may instantiate many gfxFonts for the same physical font
     408                 :      * file (at different sizes), we should ensure that they can share a
     409                 :      * single cached copy of the font tables. To do this, we implement table
     410                 :      * access and sharing on the fontEntry rather than the font itself.
     411                 :      *
     412                 :      * The default implementation uses GetFontTable() to read font table
     413                 :      * data into byte arrays, and wraps them in blobs which are registered in
     414                 :      * a hashtable.  The hashtable can then return pre-existing blobs to
     415                 :      * harfbuzz.
     416                 :      *
     417                 :      * Harfbuzz will "destroy" the blobs when it is finished with them.  When
     418                 :      * the last blob reference is removed, the FontTableBlobData user data
     419                 :      * will remove the blob from the hashtable if still registered.
     420                 :      */
     421                 : 
     422                 :     class FontTableBlobData;
     423                 : 
     424                 :     /**
     425                 :      * FontTableHashEntry manages the entries of hb_blob_ts for two
     426                 :      * different situations:
     427                 :      *
     428                 :      * The common situation is to share font table across fonts with the same
     429                 :      * font entry (but different sizes) for use by HarfBuzz.  The hashtable
     430                 :      * does not own a strong reference to the blob, but keeps a weak pointer,
     431                 :      * managed by FontTableBlobData.  Similarly FontTableBlobData keeps only a
     432                 :      * weak pointer to the hashtable, managed by FontTableHashEntry.
     433                 :      *
     434                 :      * Some font tables are saved here before they would get stripped by OTS
     435                 :      * sanitizing.  These are retained for harfbuzz, which does its own
     436                 :      * sanitizing.  The hashtable owns a reference, so ownership is simple.
     437                 :      */
     438                 : 
     439                 :     class FontTableHashEntry : public nsUint32HashKey
     440                 :     {
     441                 :     public:
     442                 :         // Declarations for nsTHashtable
     443                 : 
     444                 :         typedef nsUint32HashKey KeyClass;
     445                 :         typedef KeyClass::KeyType KeyType;
     446                 :         typedef KeyClass::KeyTypePointer KeyTypePointer;
     447                 : 
     448               0 :         FontTableHashEntry(KeyTypePointer aTag)
     449               0 :             : KeyClass(aTag), mBlob() { };
     450                 :         // Copying transfers blob association.
     451                 :         FontTableHashEntry(FontTableHashEntry& toCopy)
     452                 :             : KeyClass(toCopy), mBlob(toCopy.mBlob)
     453                 :         {
     454                 :             toCopy.mBlob = nsnull;
     455                 :         }
     456                 : 
     457               0 :         ~FontTableHashEntry() { Clear(); }
     458                 : 
     459                 :         // FontTable/Blob API
     460                 : 
     461                 :         // Transfer (not copy) elements of aTable to a new hb_blob_t and
     462                 :         // return ownership to the caller.  A weak reference to the blob is
     463                 :         // recorded in the hashtable entry so that others may use the same
     464                 :         // table.
     465                 :         hb_blob_t *
     466                 :         ShareTableAndGetBlob(FallibleTArray<PRUint8>& aTable,
     467                 :                              nsTHashtable<FontTableHashEntry> *aHashtable);
     468                 : 
     469                 :         // Transfer (not copy) elements of aTable to a new hb_blob_t that is
     470                 :         // owned by the hashtable entry.
     471                 :         void SaveTable(FallibleTArray<PRUint8>& aTable);
     472                 : 
     473                 :         // Return a strong reference to the blob.
     474                 :         // Callers must hb_blob_destroy the returned blob.
     475                 :         hb_blob_t *GetBlob() const;
     476                 : 
     477                 :         void Clear();
     478                 : 
     479                 :     private:
     480                 :         static void DeleteFontTableBlobData(void *aBlobData);
     481                 :         // not implemented
     482                 :         FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
     483                 : 
     484                 :         FontTableBlobData *mSharedBlobData;
     485                 :         hb_blob_t *mBlob;
     486                 :     };
     487                 : 
     488                 :     nsTHashtable<FontTableHashEntry> mFontTableCache;
     489                 : 
     490                 :     gfxFontEntry(const gfxFontEntry&);
     491                 :     gfxFontEntry& operator=(const gfxFontEntry&);
     492                 : };
     493                 : 
     494                 : 
     495                 : // used when iterating over all fonts looking for a match for a given character
     496               0 : struct GlobalFontMatch {
     497               0 :     GlobalFontMatch(const PRUint32 aCharacter,
     498                 :                     PRInt32 aRunScript,
     499                 :                     const gfxFontStyle *aStyle) :
     500                 :         mCh(aCharacter), mRunScript(aRunScript), mStyle(aStyle),
     501               0 :         mMatchRank(0), mCount(0), mCmapsTested(0)
     502                 :         {
     503                 : 
     504               0 :         }
     505                 : 
     506                 :     const PRUint32         mCh;          // codepoint to be matched
     507                 :     PRInt32                mRunScript;   // Unicode script for the codepoint
     508                 :     const gfxFontStyle*    mStyle;       // style to match
     509                 :     PRInt32                mMatchRank;   // metric indicating closest match
     510                 :     nsRefPtr<gfxFontEntry> mBestMatch;   // current best match
     511                 :     PRUint32               mCount;       // number of fonts matched
     512                 :     PRUint32               mCmapsTested; // number of cmaps tested
     513                 : };
     514                 : 
     515                 : class gfxFontFamily {
     516                 : public:
     517               0 :     NS_INLINE_DECL_REFCOUNTING(gfxFontFamily)
     518                 : 
     519               0 :     gfxFontFamily(const nsAString& aName) :
     520                 :         mName(aName),
     521                 :         mOtherFamilyNamesInitialized(false),
     522                 :         mHasOtherFamilyNames(false),
     523                 :         mFaceNamesInitialized(false),
     524                 :         mHasStyles(false),
     525                 :         mIsSimpleFamily(false),
     526                 :         mIsBadUnderlineFamily(false),
     527               0 :         mCharacterMapInitialized(false)
     528               0 :         { }
     529                 : 
     530               0 :     virtual ~gfxFontFamily() {
     531                 :         // clear Family pointers in our faces; the font entries might stay
     532                 :         // alive due to cached font objects, but they can no longer refer
     533                 :         // to their families.
     534               0 :         PRUint32 i = mAvailableFonts.Length();
     535               0 :         while (i) {
     536               0 :              gfxFontEntry *fe = mAvailableFonts[--i];
     537               0 :              if (fe) {
     538               0 :                  fe->SetFamily(nsnull);
     539                 :              }
     540                 :         }
     541               0 :     }
     542                 : 
     543               0 :     const nsString& Name() { return mName; }
     544                 : 
     545                 :     virtual void LocalizedName(nsAString& aLocalizedName);
     546                 :     virtual bool HasOtherFamilyNames();
     547                 :     
     548               0 :     nsTArray<nsRefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
     549                 :     
     550                 :     void AddFontEntry(nsRefPtr<gfxFontEntry> aFontEntry) {
     551                 :         // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
     552                 :         // of Times New Roman, because of buggy table in those fonts
     553                 :         if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
     554                 :             Name().EqualsLiteral("Times New Roman"))
     555                 :         {
     556                 :             aFontEntry->mIgnoreGDEF = true;
     557                 :         }
     558                 :         mAvailableFonts.AppendElement(aFontEntry);
     559                 :         aFontEntry->SetFamily(this);
     560                 :     }
     561                 : 
     562                 :     // note that the styles for this family have been added
     563                 :     void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
     564                 : 
     565                 :     // choose a specific face to match a style using CSS font matching
     566                 :     // rules (weight matching occurs here).  may return a face that doesn't
     567                 :     // precisely match (e.g. normal face when no italic face exists).
     568                 :     // aNeedsSyntheticBold is set to true when synthetic bolding is
     569                 :     // needed, false otherwise
     570                 :     gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle, 
     571                 :                                    bool& aNeedsSyntheticBold);
     572                 : 
     573                 :     // checks for a matching font within the family
     574                 :     // used as part of the font fallback process
     575                 :     void FindFontForChar(GlobalFontMatch *aMatchData);
     576                 : 
     577                 :     // checks all fonts for a matching font within the family
     578                 :     void SearchAllFontsForChar(GlobalFontMatch *aMatchData);
     579                 : 
     580                 :     // read in other family names, if any, and use functor to add each into cache
     581                 :     virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
     582                 : 
     583                 :     // set when other family names have been read in
     584                 :     void SetOtherFamilyNamesInitialized() {
     585                 :         mOtherFamilyNamesInitialized = true;
     586                 :     }
     587                 : 
     588                 :     // read in other localized family names, fullnames and Postscript names
     589                 :     // for all faces and append to lookup tables
     590                 :     virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
     591                 :                                bool aNeedFullnamePostscriptNames);
     592                 : 
     593                 :     // find faces belonging to this family (platform implementations override this;
     594                 :     // should be made pure virtual once all subclasses have been updated)
     595               0 :     virtual void FindStyleVariations() { }
     596                 : 
     597                 :     // search for a specific face using the Postscript name
     598                 :     gfxFontEntry* FindFont(const nsAString& aPostscriptName);
     599                 : 
     600                 :     // read in cmaps for all the faces
     601               0 :     void ReadAllCMAPs() {
     602               0 :         PRUint32 i, numFonts = mAvailableFonts.Length();
     603               0 :         for (i = 0; i < numFonts; i++) {
     604               0 :             gfxFontEntry *fe = mAvailableFonts[i];
     605               0 :             if (!fe) {
     606               0 :                 continue;
     607                 :             }
     608               0 :             fe->ReadCMAP();
     609               0 :             mCharacterMap.Union(fe->mCharacterMap);
     610                 :         }
     611               0 :         mCharacterMap.Compact();
     612               0 :         mCharacterMapInitialized = true;
     613               0 :     }
     614                 : 
     615               0 :     bool TestCharacterMap(PRUint32 aCh) {
     616               0 :         if (!mCharacterMapInitialized) {
     617               0 :             ReadAllCMAPs();
     618                 :         }
     619               0 :         return mCharacterMap.test(aCh);
     620                 :     }
     621                 : 
     622               0 :     void ResetCharacterMap() {
     623               0 :         mCharacterMap.reset();
     624               0 :         mCharacterMapInitialized = false;
     625               0 :     }
     626                 : 
     627                 :     // mark this family as being in the "bad" underline offset blacklist
     628               0 :     void SetBadUnderlineFamily() {
     629               0 :         mIsBadUnderlineFamily = true;
     630               0 :         if (mHasStyles) {
     631               0 :             SetBadUnderlineFonts();
     632                 :         }
     633               0 :     }
     634                 : 
     635                 :     bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
     636                 : 
     637                 :     // sort available fonts to put preferred (standard) faces towards the end
     638                 :     void SortAvailableFonts();
     639                 : 
     640                 :     // check whether the family fits into the simple 4-face model,
     641                 :     // so we can use simplified style-matching;
     642                 :     // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
     643                 :     void CheckForSimpleFamily();
     644                 : 
     645                 : protected:
     646                 :     // fills in an array with weights of faces that match style,
     647                 :     // returns whether any matching entries found
     648                 :     virtual bool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
     649                 :                                        bool anItalic, PRInt16 aStretch);
     650                 : 
     651                 :     bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
     652                 :                                        FallibleTArray<PRUint8>& aNameTable,
     653                 :                                        bool useFullName = false);
     654                 : 
     655                 :     // set whether this font family is in "bad" underline offset blacklist.
     656               0 :     void SetBadUnderlineFonts() {
     657               0 :         PRUint32 i, numFonts = mAvailableFonts.Length();
     658               0 :         for (i = 0; i < numFonts; i++) {
     659               0 :             if (mAvailableFonts[i]) {
     660               0 :                 mAvailableFonts[i]->mIsBadUnderlineFont = true;
     661                 :             }
     662                 :         }
     663               0 :     }
     664                 : 
     665                 :     nsString mName;
     666                 :     nsTArray<nsRefPtr<gfxFontEntry> >  mAvailableFonts;
     667                 :     gfxSparseBitSet mCharacterMap;
     668                 :     bool mOtherFamilyNamesInitialized;
     669                 :     bool mHasOtherFamilyNames;
     670                 :     bool mFaceNamesInitialized;
     671                 :     bool mHasStyles;
     672                 :     bool mIsSimpleFamily;
     673                 :     bool mIsBadUnderlineFamily;
     674                 :     bool mCharacterMapInitialized;
     675                 : 
     676                 :     enum {
     677                 :         // for "simple" families, the faces are stored in mAvailableFonts
     678                 :         // with fixed positions:
     679                 :         kRegularFaceIndex    = 0,
     680                 :         kBoldFaceIndex       = 1,
     681                 :         kItalicFaceIndex     = 2,
     682                 :         kBoldItalicFaceIndex = 3,
     683                 :         // mask values for selecting face with bold and/or italic attributes
     684                 :         kBoldMask   = 0x01,
     685                 :         kItalicMask = 0x02
     686                 :     };
     687                 : };
     688                 : 
     689               0 : struct gfxTextRange {
     690                 :     enum {
     691                 :         // flags for recording the kind of font-matching that was used
     692                 :         kFontGroup      = 0x0001,
     693                 :         kPrefsFallback  = 0x0002,
     694                 :         kSystemFallback = 0x0004
     695                 :     };
     696               0 :     gfxTextRange(PRUint32 aStart, PRUint32 aEnd,
     697                 :                  gfxFont* aFont, PRUint8 aMatchType)
     698                 :         : start(aStart),
     699                 :           end(aEnd),
     700                 :           font(aFont),
     701               0 :           matchType(aMatchType)
     702               0 :     { }
     703               0 :     PRUint32 Length() const { return end - start; }
     704                 :     PRUint32 start, end;
     705                 :     nsRefPtr<gfxFont> font;
     706                 :     PRUint8 matchType;
     707                 : };
     708                 : 
     709                 : 
     710                 : /**
     711                 :  * Font cache design:
     712                 :  * 
     713                 :  * The mFonts hashtable contains most fonts, indexed by (gfxFontEntry*, style).
     714                 :  * It does not add a reference to the fonts it contains.
     715                 :  * When a font's refcount decreases to zero, instead of deleting it we
     716                 :  * add it to our expiration tracker.
     717                 :  * The expiration tracker tracks fonts with zero refcount. After a certain
     718                 :  * period of time, such fonts expire and are deleted.
     719                 :  *
     720                 :  * We're using 3 generations with a ten-second generation interval, so
     721                 :  * zero-refcount fonts will be deleted 20-30 seconds after their refcount
     722                 :  * goes to zero, if timer events fire in a timely manner.
     723                 :  *
     724                 :  * The font cache also handles timed expiration of cached ShapedWords
     725                 :  * for "persistent" fonts: it has a repeating timer, and notifies
     726                 :  * each cached font to "age" its shaped words. The words will be released
     727                 :  * by the fonts if they get aged three times without being re-used in the
     728                 :  * meantime.
     729                 :  *
     730                 :  * Note that the ShapedWord timeout is much larger than the font timeout,
     731                 :  * so that in the case of a short-lived font, we'll discard the gfxFont
     732                 :  * completely, with all its words, and avoid the cost of aging the words
     733                 :  * individually. That only happens with longer-lived fonts.
     734                 :  */
     735                 : class THEBES_API gfxFontCache MOZ_FINAL : public nsExpirationTracker<gfxFont,3> {
     736                 : public:
     737                 :     enum {
     738                 :         FONT_TIMEOUT_SECONDS = 10,
     739                 :         SHAPED_WORD_TIMEOUT_SECONDS = 60
     740                 :     };
     741                 : 
     742                 :     gfxFontCache();
     743                 :     ~gfxFontCache();
     744                 : 
     745                 :     /*
     746                 :      * Get the global gfxFontCache.  You must call Init() before
     747                 :      * calling this method --- the result will not be null.
     748                 :      */
     749               0 :     static gfxFontCache* GetCache() {
     750               0 :         return gGlobalCache;
     751                 :     }
     752                 : 
     753                 :     static nsresult Init();
     754                 :     // It's OK to call this even if Init() has not been called.
     755                 :     static void Shutdown();
     756                 : 
     757                 :     // Look up a font in the cache. Returns an addrefed pointer, or null
     758                 :     // if there's nothing matching in the cache
     759                 :     already_AddRefed<gfxFont> Lookup(const gfxFontEntry *aFontEntry,
     760                 :                                      const gfxFontStyle *aStyle);
     761                 :     // We created a new font (presumably because Lookup returned null);
     762                 :     // put it in the cache. The font's refcount should be nonzero. It is
     763                 :     // allowable to add a new font even if there is one already in the
     764                 :     // cache with the same key; we'll forget about the old one.
     765                 :     void AddNew(gfxFont *aFont);
     766                 : 
     767                 :     // The font's refcount has gone to zero; give ownership of it to
     768                 :     // the cache. We delete it if it's not acquired again after a certain
     769                 :     // amount of time.
     770                 :     void NotifyReleased(gfxFont *aFont);
     771                 : 
     772                 :     // This gets called when the timeout has expired on a zero-refcount
     773                 :     // font; we just delete it.
     774                 :     virtual void NotifyExpired(gfxFont *aFont);
     775                 : 
     776                 :     // Cleans out the hashtable and removes expired fonts waiting for cleanup.
     777                 :     // Other gfxFont objects may be still in use but they will be pushed
     778                 :     // into the expiration queues and removed.
     779                 :     void Flush() {
     780                 :         mFonts.Clear();
     781                 :         AgeAllGenerations();
     782                 :     }
     783                 : 
     784               0 :     void FlushShapedWordCaches() {
     785               0 :         mFonts.EnumerateEntries(ClearCachedWordsForFont, nsnull);
     786               0 :     }
     787                 : 
     788                 : protected:
     789                 :     void DestroyFont(gfxFont *aFont);
     790                 : 
     791                 :     static gfxFontCache *gGlobalCache;
     792                 : 
     793                 :     struct Key {
     794                 :         const gfxFontEntry* mFontEntry;
     795                 :         const gfxFontStyle* mStyle;
     796               0 :         Key(const gfxFontEntry* aFontEntry, const gfxFontStyle* aStyle)
     797               0 :             : mFontEntry(aFontEntry), mStyle(aStyle) {}
     798                 :     };
     799                 : 
     800                 :     class HashEntry : public PLDHashEntryHdr {
     801                 :     public:
     802                 :         typedef const Key& KeyType;
     803                 :         typedef const Key* KeyTypePointer;
     804                 : 
     805                 :         // When constructing a new entry in the hashtable, we'll leave this
     806                 :         // blank. The caller of Put() will fill this in.
     807               0 :         HashEntry(KeyTypePointer aStr) : mFont(nsnull) { }
     808                 :         HashEntry(const HashEntry& toCopy) : mFont(toCopy.mFont) { }
     809               0 :         ~HashEntry() { }
     810                 : 
     811                 :         bool KeyEquals(const KeyTypePointer aKey) const;
     812               0 :         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
     813               0 :         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
     814               0 :             return mozilla::HashGeneric(aKey->mStyle->Hash(), aKey->mFontEntry);
     815                 :         }
     816                 :         enum { ALLOW_MEMMOVE = true };
     817                 : 
     818                 :         gfxFont* mFont;
     819                 :     };
     820                 : 
     821                 :     nsTHashtable<HashEntry> mFonts;
     822                 : 
     823                 :     static PLDHashOperator ClearCachedWordsForFont(HashEntry* aHashEntry, void*);
     824                 :     static PLDHashOperator AgeCachedWordsForFont(HashEntry* aHashEntry, void*);
     825                 :     static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
     826                 :     nsCOMPtr<nsITimer>      mWordCacheExpirationTimer;
     827                 : };
     828                 : 
     829               0 : class THEBES_API gfxTextRunFactory {
     830               0 :     NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory)
     831                 : 
     832                 : public:
     833                 :     // Flags in the mask 0xFFFF0000 are reserved for textrun clients
     834                 :     // Flags in the mask 0x0000F000 are reserved for per-platform fonts
     835                 :     // Flags in the mask 0x00000FFF are set by the textrun creator.
     836                 :     enum {
     837                 :         CACHE_TEXT_FLAGS    = 0xF0000000,
     838                 :         USER_TEXT_FLAGS     = 0x0FFF0000,
     839                 :         PLATFORM_TEXT_FLAGS = 0x0000F000,
     840                 :         TEXTRUN_TEXT_FLAGS  = 0x00000FFF,
     841                 :         SETTABLE_FLAGS      = CACHE_TEXT_FLAGS | USER_TEXT_FLAGS,
     842                 : 
     843                 :         /**
     844                 :          * When set, the text string pointer used to create the text run
     845                 :          * is guaranteed to be available during the lifetime of the text run.
     846                 :          */
     847                 :         TEXT_IS_PERSISTENT           = 0x0001,
     848                 :         /**
     849                 :          * When set, the text is known to be all-ASCII (< 128).
     850                 :          */
     851                 :         TEXT_IS_ASCII                = 0x0002,
     852                 :         /**
     853                 :          * When set, the text is RTL.
     854                 :          */
     855                 :         TEXT_IS_RTL                  = 0x0004,
     856                 :         /**
     857                 :          * When set, spacing is enabled and the textrun needs to call GetSpacing
     858                 :          * on the spacing provider.
     859                 :          */
     860                 :         TEXT_ENABLE_SPACING          = 0x0008,
     861                 :         /**
     862                 :          * When set, GetHyphenationBreaks may return true for some character
     863                 :          * positions, otherwise it will always return false for all characters.
     864                 :          */
     865                 :         TEXT_ENABLE_HYPHEN_BREAKS    = 0x0010,
     866                 :         /**
     867                 :          * When set, the text has no characters above 255 and it is stored
     868                 :          * in the textrun in 8-bit format.
     869                 :          */
     870                 :         TEXT_IS_8BIT                 = 0x0020,
     871                 :         /**
     872                 :          * When set, the RunMetrics::mBoundingBox field will be initialized
     873                 :          * properly based on glyph extents, in particular, glyph extents that
     874                 :          * overflow the standard font-box (the box defined by the ascent, descent
     875                 :          * and advance width of the glyph). When not set, it may just be the
     876                 :          * standard font-box even if glyphs overflow.
     877                 :          */
     878                 :         TEXT_NEED_BOUNDING_BOX       = 0x0040,
     879                 :         /**
     880                 :          * When set, optional ligatures are disabled. Ligatures that are
     881                 :          * required for legible text should still be enabled.
     882                 :          */
     883                 :         TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0080,
     884                 :         /**
     885                 :          * When set, the textrun should favour speed of construction over
     886                 :          * quality. This may involve disabling ligatures and/or kerning or
     887                 :          * other effects.
     888                 :          */
     889                 :         TEXT_OPTIMIZE_SPEED          = 0x0100,
     890                 :         /**
     891                 :          * For internal use by the memory reporter when accounting for
     892                 :          * storage used by textruns.
     893                 :          * Because the reporter may visit each textrun multiple times while
     894                 :          * walking the frame trees and textrun cache, it needs to mark
     895                 :          * textruns that have been seen so as to avoid multiple-accounting.
     896                 :          */
     897                 :         TEXT_RUN_SIZE_ACCOUNTED      = 0x0200,
     898                 : 
     899                 :         /**
     900                 :          * nsTextFrameThebes sets these, but they're defined here rather than
     901                 :          * in nsTextFrameUtils.h because ShapedWord creation/caching also needs
     902                 :          * to check the _INCOMING flag
     903                 :          */
     904                 :         TEXT_TRAILING_ARABICCHAR = 0x20000000,
     905                 :         /**
     906                 :          * When set, the previous character for this textrun was an Arabic
     907                 :          * character.  This is used for the context detection necessary for
     908                 :          * bidi.numeral implementation.
     909                 :          */
     910                 :         TEXT_INCOMING_ARABICCHAR = 0x40000000,
     911                 : 
     912                 :         TEXT_UNUSED_FLAGS = 0x90000000
     913                 :     };
     914                 : 
     915                 :     /**
     916                 :      * This record contains all the parameters needed to initialize a textrun.
     917                 :      */
     918                 :     struct Parameters {
     919                 :         // A reference context suggesting where the textrun will be rendered
     920                 :         gfxContext   *mContext;
     921                 :         // Pointer to arbitrary user data (which should outlive the textrun)
     922                 :         void         *mUserData;
     923                 :         // A description of which characters have been stripped from the original
     924                 :         // DOM string to produce the characters in the textrun. May be null
     925                 :         // if that information is not relevant.
     926                 :         gfxSkipChars *mSkipChars;
     927                 :         // A list of where linebreaks are currently placed in the textrun. May
     928                 :         // be null if mInitialBreakCount is zero.
     929                 :         PRUint32     *mInitialBreaks;
     930                 :         PRUint32      mInitialBreakCount;
     931                 :         // The ratio to use to convert device pixels to application layout units
     932                 :         PRUint32      mAppUnitsPerDevUnit;
     933                 :     };
     934                 : 
     935               0 :     virtual ~gfxTextRunFactory() {}
     936                 : };
     937                 : 
     938                 : /**
     939                 :  * This stores glyph bounds information for a particular gfxFont, at
     940                 :  * a particular appunits-per-dev-pixel ratio (because the compressed glyph
     941                 :  * width array is stored in appunits).
     942                 :  * 
     943                 :  * We store a hashtable from glyph IDs to float bounding rects. For the
     944                 :  * common case where the glyph has no horizontal left bearing, and no
     945                 :  * y overflow above the font ascent or below the font descent, and tight
     946                 :  * bounding boxes are not required, we avoid storing the glyph ID in the hashtable
     947                 :  * and instead consult an array of 16-bit glyph XMost values (in appunits).
     948                 :  * This array always has an entry for the font's space glyph --- the width is
     949                 :  * assumed to be zero.
     950                 :  */
     951                 : class THEBES_API gfxGlyphExtents {
     952                 : public:
     953               0 :     gfxGlyphExtents(PRUint32 aAppUnitsPerDevUnit) :
     954               0 :         mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) {
     955               0 :         MOZ_COUNT_CTOR(gfxGlyphExtents);
     956               0 :         mTightGlyphExtents.Init();
     957               0 :     }
     958                 :     ~gfxGlyphExtents();
     959                 : 
     960                 :     enum { INVALID_WIDTH = 0xFFFF };
     961                 : 
     962                 :     // returns INVALID_WIDTH => not a contained glyph
     963                 :     // Otherwise the glyph has no before-bearing or vertical bearings,
     964                 :     // and the result is its width measured from the baseline origin, in
     965                 :     // appunits.
     966               0 :     PRUint16 GetContainedGlyphWidthAppUnits(PRUint32 aGlyphID) const {
     967               0 :         return mContainedGlyphWidths.Get(aGlyphID);
     968                 :     }
     969                 : 
     970               0 :     bool IsGlyphKnown(PRUint32 aGlyphID) const {
     971               0 :         return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
     972               0 :             mTightGlyphExtents.GetEntry(aGlyphID) != nsnull;
     973                 :     }
     974                 : 
     975               0 :     bool IsGlyphKnownWithTightExtents(PRUint32 aGlyphID) const {
     976               0 :         return mTightGlyphExtents.GetEntry(aGlyphID) != nsnull;
     977                 :     }
     978                 : 
     979                 :     // Get glyph extents; a rectangle relative to the left baseline origin
     980                 :     // Returns true on success. Can fail on OOM or when aContext is null
     981                 :     // and extents were not (successfully) prefetched.
     982                 :     bool GetTightGlyphExtentsAppUnits(gfxFont *aFont, gfxContext *aContext,
     983                 :             PRUint32 aGlyphID, gfxRect *aExtents);
     984                 : 
     985               0 :     void SetContainedGlyphWidthAppUnits(PRUint32 aGlyphID, PRUint16 aWidth) {
     986               0 :         mContainedGlyphWidths.Set(aGlyphID, aWidth);
     987               0 :     }
     988                 :     void SetTightGlyphExtents(PRUint32 aGlyphID, const gfxRect& aExtentsAppUnits);
     989                 : 
     990               0 :     PRUint32 GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; }
     991                 : 
     992                 : private:
     993               0 :     class HashEntry : public nsUint32HashKey {
     994                 :     public:
     995                 :         // When constructing a new entry in the hashtable, we'll leave this
     996                 :         // blank. The caller of Put() will fill this in.
     997               0 :         HashEntry(KeyTypePointer aPtr) : nsUint32HashKey(aPtr) {}
     998                 :         HashEntry(const HashEntry& toCopy) : nsUint32HashKey(toCopy) {
     999                 :           x = toCopy.x; y = toCopy.y; width = toCopy.width; height = toCopy.height;
    1000                 :         }
    1001                 : 
    1002                 :         float x, y, width, height;
    1003                 :     };
    1004                 : 
    1005                 :     typedef PRUptrdiff PtrBits;
    1006                 :     enum { BLOCK_SIZE_BITS = 7, BLOCK_SIZE = 1 << BLOCK_SIZE_BITS }; // 128-glyph blocks
    1007                 : 
    1008               0 :     class GlyphWidths {
    1009                 :     public:
    1010                 :         void Set(PRUint32 aIndex, PRUint16 aValue);
    1011               0 :         PRUint16 Get(PRUint32 aIndex) const {
    1012               0 :             PRUint32 block = aIndex >> BLOCK_SIZE_BITS;
    1013               0 :             if (block >= mBlocks.Length())
    1014               0 :                 return INVALID_WIDTH;
    1015               0 :             PtrBits bits = mBlocks[block];
    1016               0 :             if (!bits)
    1017               0 :                 return INVALID_WIDTH;
    1018               0 :             PRUint32 indexInBlock = aIndex & (BLOCK_SIZE - 1);
    1019               0 :             if (bits & 0x1) {
    1020               0 :                 if (GetGlyphOffset(bits) != indexInBlock)
    1021               0 :                     return INVALID_WIDTH;
    1022               0 :                 return GetWidth(bits);
    1023                 :             }
    1024               0 :             PRUint16 *widths = reinterpret_cast<PRUint16 *>(bits);
    1025               0 :             return widths[indexInBlock];
    1026                 :         }
    1027                 : 
    1028                 : #ifdef DEBUG
    1029                 :         PRUint32 ComputeSize();
    1030                 : #endif
    1031                 :         
    1032                 :         ~GlyphWidths();
    1033                 : 
    1034                 :     private:
    1035               0 :         static PRUint32 GetGlyphOffset(PtrBits aBits) {
    1036               0 :             NS_ASSERTION(aBits & 0x1, "This is really a pointer...");
    1037               0 :             return (aBits >> 1) & ((1 << BLOCK_SIZE_BITS) - 1);
    1038                 :         }
    1039               0 :         static PRUint32 GetWidth(PtrBits aBits) {
    1040               0 :             NS_ASSERTION(aBits & 0x1, "This is really a pointer...");
    1041               0 :             return aBits >> (1 + BLOCK_SIZE_BITS);
    1042                 :         }
    1043               0 :         static PtrBits MakeSingle(PRUint32 aGlyphOffset, PRUint16 aWidth) {
    1044               0 :             return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1;
    1045                 :         }
    1046                 : 
    1047                 :         nsTArray<PtrBits> mBlocks;
    1048                 :     };
    1049                 :     
    1050                 :     GlyphWidths             mContainedGlyphWidths;
    1051                 :     nsTHashtable<HashEntry> mTightGlyphExtents;
    1052                 :     PRUint32                mAppUnitsPerDevUnit;
    1053                 : };
    1054                 : 
    1055                 : /**
    1056                 :  * gfxFontShaper
    1057                 :  *
    1058                 :  * This class implements text shaping (character to glyph mapping and
    1059                 :  * glyph layout). There is a gfxFontShaper subclass for each text layout
    1060                 :  * technology (uniscribe, core text, harfbuzz,....) we support.
    1061                 :  *
    1062                 :  * The shaper is responsible for setting up glyph data in gfxTextRuns.
    1063                 :  *
    1064                 :  * A generic, platform-independent shaper relies only on the standard
    1065                 :  * gfxFont interface and can work with any concrete subclass of gfxFont.
    1066                 :  *
    1067                 :  * Platform-specific implementations designed to interface to platform
    1068                 :  * shaping APIs such as Uniscribe or CoreText may rely on features of a
    1069                 :  * specific font subclass to access native font references
    1070                 :  * (such as CTFont, HFONT, DWriteFont, etc).
    1071                 :  */
    1072                 : 
    1073                 : class gfxFontShaper {
    1074                 : public:
    1075               0 :     gfxFontShaper(gfxFont *aFont)
    1076               0 :         : mFont(aFont)
    1077                 :     {
    1078               0 :         NS_ASSERTION(aFont, "shaper requires a valid font!");
    1079               0 :     }
    1080                 : 
    1081               0 :     virtual ~gfxFontShaper() { }
    1082                 : 
    1083                 :     virtual bool ShapeWord(gfxContext *aContext,
    1084                 :                            gfxShapedWord *aShapedWord,
    1085                 :                            const PRUnichar *aText) = 0;
    1086                 : 
    1087               0 :     gfxFont *GetFont() const { return mFont; }
    1088                 : 
    1089                 : protected:
    1090                 :     // the font this shaper is working with
    1091                 :     gfxFont * mFont;
    1092                 : };
    1093                 : 
    1094                 : /* a SPECIFIC single font family */
    1095                 : class THEBES_API gfxFont {
    1096                 : public:
    1097               0 :     nsrefcnt AddRef(void) {
    1098               0 :         NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
    1099               0 :         if (mExpirationState.IsTracked()) {
    1100               0 :             gfxFontCache::GetCache()->RemoveObject(this);
    1101                 :         }
    1102               0 :         ++mRefCnt;
    1103               0 :         NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this));
    1104               0 :         return mRefCnt;
    1105                 :     }
    1106               0 :     nsrefcnt Release(void) {
    1107               0 :         NS_PRECONDITION(0 != mRefCnt, "dup release");
    1108               0 :         --mRefCnt;
    1109               0 :         NS_LOG_RELEASE(this, mRefCnt, "gfxFont");
    1110               0 :         if (mRefCnt == 0) {
    1111               0 :             NotifyReleased();
    1112                 :             // |this| may have been deleted.
    1113               0 :             return 0;
    1114                 :         }
    1115               0 :         return mRefCnt;
    1116                 :     }
    1117                 : 
    1118               0 :     PRInt32 GetRefCount() { return mRefCnt; }
    1119                 : 
    1120                 :     // options to specify the kind of AA to be used when creating a font
    1121                 :     typedef enum {
    1122                 :         kAntialiasDefault,
    1123                 :         kAntialiasNone,
    1124                 :         kAntialiasGrayscale,
    1125                 :         kAntialiasSubpixel
    1126                 :     } AntialiasOption;
    1127                 : 
    1128                 :     // Options for how the text should be drawn
    1129                 :     typedef enum {
    1130                 :         // GLYPH_FILL and GLYPH_STROKE draw into the current context
    1131                 :         //  and may be used together with bitwise OR.
    1132                 :         GLYPH_FILL = 1,
    1133                 :         // Note: using GLYPH_STROKE will destroy the current path.
    1134                 :         GLYPH_STROKE = 2,
    1135                 :         // Appends glyphs to the current path. Can NOT be used with
    1136                 :         //  GLYPH_FILL or GLYPH_STROKE.
    1137                 :         GLYPH_PATH = 4
    1138                 :     } DrawMode;
    1139                 : 
    1140                 : protected:
    1141                 :     nsAutoRefCnt mRefCnt;
    1142                 :     cairo_scaled_font_t *mScaledFont;
    1143                 : 
    1144               0 :     void NotifyReleased() {
    1145               0 :         gfxFontCache *cache = gfxFontCache::GetCache();
    1146               0 :         if (cache) {
    1147                 :             // Don't delete just yet; return the object to the cache for
    1148                 :             // possibly recycling within some time limit
    1149               0 :             cache->NotifyReleased(this);
    1150                 :         } else {
    1151                 :             // The cache may have already been shut down.
    1152               0 :             delete this;
    1153                 :         }
    1154               0 :     }
    1155                 : 
    1156                 :     gfxFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
    1157                 :             AntialiasOption anAAOption = kAntialiasDefault,
    1158                 :             cairo_scaled_font_t *aScaledFont = nsnull);
    1159                 : 
    1160                 : public:
    1161                 :     virtual ~gfxFont();
    1162                 : 
    1163               0 :     bool Valid() const {
    1164               0 :         return mIsValid;
    1165                 :     }
    1166                 : 
    1167                 :     // options for the kind of bounding box to return from measurement
    1168                 :     typedef enum {
    1169                 :         LOOSE_INK_EXTENTS,
    1170                 :             // A box that encloses all the painted pixels, and may
    1171                 :             // include sidebearings and/or additional ascent/descent
    1172                 :             // within the glyph cell even if the ink is smaller.
    1173                 :         TIGHT_INK_EXTENTS,
    1174                 :             // A box that tightly encloses all the painted pixels
    1175                 :             // (although actually on Windows, at least, it may be
    1176                 :             // slightly larger than strictly necessary because
    1177                 :             // we can't get precise extents with ClearType).
    1178                 :         TIGHT_HINTED_OUTLINE_EXTENTS
    1179                 :             // A box that tightly encloses the glyph outline,
    1180                 :             // ignoring possible antialiasing pixels that extend
    1181                 :             // beyond this.
    1182                 :             // NOTE: The default implementation of gfxFont::Measure(),
    1183                 :             // which works with the glyph extents cache, does not
    1184                 :             // differentiate between this and TIGHT_INK_EXTENTS.
    1185                 :             // Whether the distinction is important depends on the
    1186                 :             // antialiasing behavior of the platform; currently the
    1187                 :             // distinction is only implemented in the gfxWindowsFont
    1188                 :             // subclass, because of ClearType's tendency to paint
    1189                 :             // outside the hinted outline.
    1190                 :             // Also NOTE: it is relatively expensive to request this,
    1191                 :             // as it does not use cached glyph extents in the font.
    1192                 :     } BoundingBoxType;
    1193                 : 
    1194               0 :     const nsString& GetName() const { return mFontEntry->Name(); }
    1195               0 :     const gfxFontStyle *GetStyle() const { return &mStyle; }
    1196                 : 
    1197                 :     cairo_scaled_font_t* GetCairoScaledFont() { return mScaledFont; }
    1198                 : 
    1199               0 :     virtual gfxFont* CopyWithAntialiasOption(AntialiasOption anAAOption) {
    1200                 :         // platforms where this actually matters should override
    1201               0 :         return nsnull;
    1202                 :     }
    1203                 : 
    1204               0 :     virtual gfxFloat GetAdjustedSize() {
    1205               0 :         return mAdjustedSize > 0.0 ? mAdjustedSize : mStyle.size;
    1206                 :     }
    1207                 : 
    1208               0 :     float FUnitsToDevUnitsFactor() const {
    1209                 :         // check this was set up during font initialization
    1210               0 :         NS_ASSERTION(mFUnitsConvFactor > 0.0f, "mFUnitsConvFactor not valid");
    1211               0 :         return mFUnitsConvFactor;
    1212                 :     }
    1213                 : 
    1214                 :     // check whether this is an sfnt we can potentially use with harfbuzz
    1215                 :     bool FontCanSupportHarfBuzz() {
    1216                 :         return mFontEntry->HasCmapTable();
    1217                 :     }
    1218                 : 
    1219                 : #ifdef MOZ_GRAPHITE
    1220                 :     // check whether this is an sfnt we can potentially use with Graphite
    1221               0 :     bool FontCanSupportGraphite() {
    1222               0 :         return mFontEntry->HasGraphiteTables();
    1223                 :     }
    1224                 : #endif
    1225                 : 
    1226                 :     // Access to raw font table data (needed for Harfbuzz):
    1227                 :     // returns a pointer to data owned by the fontEntry or the OS,
    1228                 :     // which will remain valid until released.
    1229                 :     //
    1230                 :     // Default implementations forward to the font entry,
    1231                 :     // and maintain a shared table.
    1232                 :     //
    1233                 :     // Subclasses should override this if they can provide more efficient
    1234                 :     // access than getting tables with mFontEntry->GetFontTable() and sharing
    1235                 :     // them via the entry.
    1236                 :     //
    1237                 :     // Get pointer to a specific font table, or NULL if
    1238                 :     // the table doesn't exist in the font
    1239                 :     virtual hb_blob_t *GetFontTable(PRUint32 aTag);
    1240                 : 
    1241                 :     // Subclasses may choose to look up glyph ids for characters.
    1242                 :     // If they do not override this, gfxHarfBuzzShaper will fetch the cmap
    1243                 :     // table and use that.
    1244               0 :     virtual bool ProvidesGetGlyph() const {
    1245               0 :         return false;
    1246                 :     }
    1247                 :     // Map unicode character to glyph ID.
    1248                 :     // Only used if ProvidesGetGlyph() returns true.
    1249               0 :     virtual PRUint32 GetGlyph(PRUint32 unicode, PRUint32 variation_selector) {
    1250               0 :         return 0;
    1251                 :     }
    1252                 : 
    1253                 :     // subclasses may provide (possibly hinted) glyph widths (in font units);
    1254                 :     // if they do not override this, harfbuzz will use unhinted widths
    1255                 :     // derived from the font tables
    1256               0 :     virtual bool ProvidesGlyphWidths() {
    1257               0 :         return false;
    1258                 :     }
    1259                 : 
    1260                 :     // The return value is interpreted as a horizontal advance in 16.16 fixed
    1261                 :     // point format.
    1262               0 :     virtual PRInt32 GetGlyphWidth(gfxContext *aCtx, PRUint16 aGID) {
    1263               0 :         return -1;
    1264                 :     }
    1265                 : 
    1266                 :     gfxFloat SynthesizeSpaceWidth(PRUint32 aCh);
    1267                 : 
    1268                 :     // Font metrics
    1269                 :     struct Metrics {
    1270                 :         gfxFloat xHeight;
    1271                 :         gfxFloat superscriptOffset;
    1272                 :         gfxFloat subscriptOffset;
    1273                 :         gfxFloat strikeoutSize;
    1274                 :         gfxFloat strikeoutOffset;
    1275                 :         gfxFloat underlineSize;
    1276                 :         gfxFloat underlineOffset;
    1277                 : 
    1278                 :         gfxFloat internalLeading;
    1279                 :         gfxFloat externalLeading;
    1280                 : 
    1281                 :         gfxFloat emHeight;
    1282                 :         gfxFloat emAscent;
    1283                 :         gfxFloat emDescent;
    1284                 :         gfxFloat maxHeight;
    1285                 :         gfxFloat maxAscent;
    1286                 :         gfxFloat maxDescent;
    1287                 :         gfxFloat maxAdvance;
    1288                 : 
    1289                 :         gfxFloat aveCharWidth;
    1290                 :         gfxFloat spaceWidth;
    1291                 :         gfxFloat zeroOrAveCharWidth;  // width of '0', or if there is
    1292                 :                                       // no '0' glyph in this font,
    1293                 :                                       // equal to .aveCharWidth
    1294                 :     };
    1295                 :     virtual const gfxFont::Metrics& GetMetrics() = 0;
    1296                 : 
    1297                 :     /**
    1298                 :      * We let layout specify spacing on either side of any
    1299                 :      * character. We need to specify both before and after
    1300                 :      * spacing so that substring measurement can do the right things.
    1301                 :      * These values are in appunits. They're always an integral number of
    1302                 :      * appunits, but we specify them in floats in case very large spacing
    1303                 :      * values are required.
    1304                 :      */
    1305               0 :     struct Spacing {
    1306                 :         gfxFloat mBefore;
    1307                 :         gfxFloat mAfter;
    1308                 :     };
    1309                 :     /**
    1310                 :      * Metrics for a particular string
    1311                 :      */
    1312                 :     struct THEBES_API RunMetrics {
    1313               0 :         RunMetrics() {
    1314               0 :             mAdvanceWidth = mAscent = mDescent = 0.0;
    1315               0 :             mBoundingBox = gfxRect(0,0,0,0);
    1316               0 :         }
    1317                 : 
    1318                 :         void CombineWith(const RunMetrics& aOther, bool aOtherIsOnLeft);
    1319                 : 
    1320                 :         // can be negative (partly due to negative spacing).
    1321                 :         // Advance widths should be additive: the advance width of the
    1322                 :         // (offset1, length1) plus the advance width of (offset1 + length1,
    1323                 :         // length2) should be the advance width of (offset1, length1 + length2)
    1324                 :         gfxFloat mAdvanceWidth;
    1325                 :         
    1326                 :         // For zero-width substrings, these must be zero!
    1327                 :         gfxFloat mAscent;  // always non-negative
    1328                 :         gfxFloat mDescent; // always non-negative
    1329                 :         
    1330                 :         // Bounding box that is guaranteed to include everything drawn.
    1331                 :         // If a tight boundingBox was requested when these metrics were
    1332                 :         // generated, this will tightly wrap the glyphs, otherwise it is
    1333                 :         // "loose" and may be larger than the true bounding box.
    1334                 :         // Coordinates are relative to the baseline left origin, so typically
    1335                 :         // mBoundingBox.y == -mAscent
    1336                 :         gfxRect  mBoundingBox;
    1337                 :     };
    1338                 : 
    1339                 :     /**
    1340                 :      * Draw a series of glyphs to aContext. The direction of aTextRun must
    1341                 :      * be honoured.
    1342                 :      * @param aStart the first character to draw
    1343                 :      * @param aEnd draw characters up to here
    1344                 :      * @param aBaselineOrigin the baseline origin; the left end of the baseline
    1345                 :      * for LTR textruns, the right end of the baseline for RTL textruns. On return,
    1346                 :      * this should be updated to the other end of the baseline. In application
    1347                 :      * units, really!
    1348                 :      * @param aSpacing spacing to insert before and after characters (for RTL
    1349                 :      * glyphs, before-spacing is inserted to the right of characters). There
    1350                 :      * are aEnd - aStart elements in this array, unless it's null to indicate
    1351                 :      * that there is no spacing.
    1352                 :      * @param aDrawMode specifies whether the fill or stroke of the glyph should be
    1353                 :      * drawn, or if it should be drawn into the current path
    1354                 :      * 
    1355                 :      * Callers guarantee:
    1356                 :      * -- aStart and aEnd are aligned to cluster and ligature boundaries
    1357                 :      * -- all glyphs use this font
    1358                 :      * 
    1359                 :      * The default implementation builds a cairo glyph array and
    1360                 :      * calls cairo_show_glyphs or cairo_glyph_path.
    1361                 :      */
    1362                 :     virtual void Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
    1363                 :                       gfxContext *aContext, DrawMode aDrawMode, gfxPoint *aBaselineOrigin,
    1364                 :                       Spacing *aSpacing, gfxPattern *aStrokePattern);
    1365                 : 
    1366                 :     /**
    1367                 :      * Measure a run of characters. See gfxTextRun::Metrics.
    1368                 :      * @param aTight if false, then return the union of the glyph extents
    1369                 :      * with the font-box for the characters (the rectangle with x=0,width=
    1370                 :      * the advance width for the character run,y=-(font ascent), and height=
    1371                 :      * font ascent + font descent). Otherwise, we must return as tight as possible
    1372                 :      * an approximation to the area actually painted by glyphs.
    1373                 :      * @param aContextForTightBoundingBox when aTight is true, this must
    1374                 :      * be non-null.
    1375                 :      * @param aSpacing spacing to insert before and after glyphs. The bounding box
    1376                 :      * need not include the spacing itself, but the spacing affects the glyph
    1377                 :      * positions. null if there is no spacing.
    1378                 :      * 
    1379                 :      * Callers guarantee:
    1380                 :      * -- aStart and aEnd are aligned to cluster and ligature boundaries
    1381                 :      * -- all glyphs use this font
    1382                 :      * 
    1383                 :      * The default implementation just uses font metrics and aTextRun's
    1384                 :      * advances, and assumes no characters fall outside the font box. In
    1385                 :      * general this is insufficient, because that assumption is not always true.
    1386                 :      */
    1387                 :     virtual RunMetrics Measure(gfxTextRun *aTextRun,
    1388                 :                                PRUint32 aStart, PRUint32 aEnd,
    1389                 :                                BoundingBoxType aBoundingBoxType,
    1390                 :                                gfxContext *aContextForTightBoundingBox,
    1391                 :                                Spacing *aSpacing);
    1392                 :     /**
    1393                 :      * Line breaks have been changed at the beginning and/or end of a substring
    1394                 :      * of the text. Reshaping may be required; glyph updating is permitted.
    1395                 :      * @return true if anything was changed, false otherwise
    1396                 :      */
    1397                 :     bool NotifyLineBreaksChanged(gfxTextRun *aTextRun,
    1398                 :                                    PRUint32 aStart, PRUint32 aLength)
    1399                 :     { return false; }
    1400                 : 
    1401                 :     // Expiration tracking
    1402               0 :     nsExpirationState *GetExpirationState() { return &mExpirationState; }
    1403                 : 
    1404                 :     // Get the glyphID of a space
    1405                 :     virtual PRUint32 GetSpaceGlyph() = 0;
    1406                 : 
    1407                 :     gfxGlyphExtents *GetOrCreateGlyphExtents(PRUint32 aAppUnitsPerDevUnit);
    1408                 : 
    1409                 :     // You need to call SetupCairoFont on the aCR just before calling this
    1410                 :     virtual void SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID,
    1411                 :                                    bool aNeedTight, gfxGlyphExtents *aExtents);
    1412                 : 
    1413                 :     // This is called by the default Draw() implementation above.
    1414                 :     virtual bool SetupCairoFont(gfxContext *aContext) = 0;
    1415                 : 
    1416               0 :     bool IsSyntheticBold() { return mApplySyntheticBold; }
    1417                 : 
    1418                 :     // Amount by which synthetic bold "fattens" the glyphs: 1/16 of the em-size
    1419               0 :     gfxFloat GetSyntheticBoldOffset() {
    1420               0 :         return GetAdjustedSize() * (1.0 / 16.0);
    1421                 :     }
    1422                 : 
    1423               0 :     gfxFontEntry *GetFontEntry() { return mFontEntry.get(); }
    1424               0 :     bool HasCharacter(PRUint32 ch) {
    1425               0 :         if (!mIsValid)
    1426               0 :             return false;
    1427               0 :         return mFontEntry->HasCharacter(ch); 
    1428                 :     }
    1429                 : 
    1430                 :     PRUint16 GetUVSGlyph(PRUint32 aCh, PRUint32 aVS) {
    1431                 :         if (!mIsValid) {
    1432                 :             return 0;
    1433                 :         }
    1434                 :         return mFontEntry->GetUVSGlyph(aCh, aVS); 
    1435                 :     }
    1436                 : 
    1437                 :     // call the (virtual) InitTextRun method to do glyph generation/shaping,
    1438                 :     // limiting the length of text passed by processing the run in multiple
    1439                 :     // segments if necessary
    1440                 :     template<typename T>
    1441                 :     bool SplitAndInitTextRun(gfxContext *aContext,
    1442                 :                              gfxTextRun *aTextRun,
    1443                 :                              const T *aString,
    1444                 :                              PRUint32 aRunStart,
    1445                 :                              PRUint32 aRunLength,
    1446                 :                              PRInt32 aRunScript);
    1447                 : 
    1448                 :     // Get a ShapedWord representing the given text (either 8- or 16-bit)
    1449                 :     // for use in setting up a gfxTextRun.
    1450                 :     template<typename T>
    1451                 :     gfxShapedWord* GetShapedWord(gfxContext *aContext,
    1452                 :                                  const T *aText,
    1453                 :                                  PRUint32 aLength,
    1454                 :                                  PRUint32 aHash,
    1455                 :                                  PRInt32 aRunScript,
    1456                 :                                  PRInt32 aAppUnitsPerDevUnit,
    1457                 :                                  PRUint32 aFlags);
    1458                 : 
    1459                 :     // Ensure the ShapedWord cache is initialized. This MUST be called before
    1460                 :     // any attempt to use GetShapedWord().
    1461               0 :     void InitWordCache() {
    1462               0 :         if (!mWordCache.IsInitialized()) {
    1463               0 :             mWordCache.Init();
    1464                 :         }
    1465               0 :     }
    1466                 : 
    1467                 :     // Called by the gfxFontCache timer to increment the age of all the words,
    1468                 :     // so that they'll expire after a sufficient period of non-use
    1469               0 :     void AgeCachedWords() {
    1470               0 :         if (mWordCache.IsInitialized()) {
    1471               0 :             (void)mWordCache.EnumerateEntries(AgeCacheEntry, this);
    1472                 :         }
    1473               0 :     }
    1474                 : 
    1475                 :     // Discard all cached word records; called on memory-pressure notification.
    1476               0 :     void ClearCachedWords() {
    1477               0 :         if (mWordCache.IsInitialized()) {
    1478               0 :             mWordCache.Clear();
    1479                 :         }
    1480               0 :     }
    1481                 : 
    1482                 : protected:
    1483                 :     // Call the appropriate shaper to generate glyphs for aText and store
    1484                 :     // them into aShapedWord.
    1485                 :     // The length of the text is aShapedWord->Length().
    1486                 :     virtual bool ShapeWord(gfxContext *aContext,
    1487                 :                            gfxShapedWord *aShapedWord,
    1488                 :                            const PRUnichar *aText,
    1489                 :                            bool aPreferPlatformShaping = false);
    1490                 : 
    1491                 :     nsRefPtr<gfxFontEntry> mFontEntry;
    1492                 : 
    1493                 :     struct CacheHashKey {
    1494                 :         union {
    1495                 :             const PRUint8   *mSingle;
    1496                 :             const PRUnichar *mDouble;
    1497                 :         }                mText;
    1498                 :         PRUint32         mLength;
    1499                 :         PRUint32         mFlags;
    1500                 :         PRInt32          mScript;
    1501                 :         PRInt32          mAppUnitsPerDevUnit;
    1502                 :         PLDHashNumber    mHashKey;
    1503                 :         bool             mTextIs8Bit;
    1504                 : 
    1505               0 :         CacheHashKey(const PRUint8 *aText, PRUint32 aLength,
    1506                 :                      PRUint32 aStringHash,
    1507                 :                      PRInt32 aScriptCode, PRInt32 aAppUnitsPerDevUnit,
    1508                 :                      PRUint32 aFlags)
    1509                 :             : mLength(aLength),
    1510                 :               mFlags(aFlags),
    1511                 :               mScript(aScriptCode),
    1512                 :               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
    1513                 :               mHashKey(aStringHash + aScriptCode +
    1514                 :                   aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
    1515               0 :               mTextIs8Bit(true)
    1516                 :         {
    1517               0 :             NS_ASSERTION(aFlags & gfxTextRunFactory::TEXT_IS_8BIT,
    1518                 :                          "8-bit flag should have been set");
    1519               0 :             mText.mSingle = aText;
    1520               0 :         }
    1521                 : 
    1522               0 :         CacheHashKey(const PRUnichar *aText, PRUint32 aLength,
    1523                 :                      PRUint32 aStringHash,
    1524                 :                      PRInt32 aScriptCode, PRInt32 aAppUnitsPerDevUnit,
    1525                 :                      PRUint32 aFlags)
    1526                 :             : mLength(aLength),
    1527                 :               mFlags(aFlags),
    1528                 :               mScript(aScriptCode),
    1529                 :               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
    1530                 :               mHashKey(aStringHash + aScriptCode +
    1531                 :                   aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
    1532               0 :               mTextIs8Bit(false)
    1533                 :         {
    1534                 :             // We can NOT assert that TEXT_IS_8BIT is false in aFlags here,
    1535                 :             // because this might be an 8bit-only word from a 16-bit textrun,
    1536                 :             // in which case the text we're passed is still in 16-bit form,
    1537                 :             // and we'll have to use an 8-to-16bit comparison in KeyEquals.
    1538               0 :             mText.mDouble = aText;
    1539               0 :         }
    1540                 :     };
    1541                 : 
    1542                 :     class CacheHashEntry : public PLDHashEntryHdr {
    1543                 :     public:
    1544                 :         typedef const CacheHashKey &KeyType;
    1545                 :         typedef const CacheHashKey *KeyTypePointer;
    1546                 : 
    1547                 :         // When constructing a new entry in the hashtable, the caller of Put()
    1548                 :         // will fill us in.
    1549               0 :         CacheHashEntry(KeyTypePointer aKey) { }
    1550                 :         CacheHashEntry(const CacheHashEntry& toCopy) { NS_ERROR("Should not be called"); }
    1551               0 :         ~CacheHashEntry() { }
    1552                 : 
    1553                 :         bool KeyEquals(const KeyTypePointer aKey) const;
    1554                 : 
    1555               0 :         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
    1556                 : 
    1557               0 :         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
    1558               0 :             return aKey->mHashKey;
    1559                 :         }
    1560                 : 
    1561                 :         enum { ALLOW_MEMMOVE = true };
    1562                 : 
    1563                 :         nsAutoPtr<gfxShapedWord> mShapedWord;
    1564                 :     };
    1565                 : 
    1566                 :     nsTHashtable<CacheHashEntry> mWordCache;
    1567                 : 
    1568                 :     static PLDHashOperator AgeCacheEntry(CacheHashEntry *aEntry, void *aUserData);
    1569                 :     static const PRUint32  kShapedWordCacheMaxAge = 3;
    1570                 : 
    1571                 :     bool                       mIsValid;
    1572                 : 
    1573                 :     // use synthetic bolding for environments where this is not supported
    1574                 :     // by the platform
    1575                 :     bool                       mApplySyntheticBold;
    1576                 : 
    1577                 :     nsExpirationState          mExpirationState;
    1578                 :     gfxFontStyle               mStyle;
    1579                 :     nsAutoTArray<gfxGlyphExtents*,1> mGlyphExtentsArray;
    1580                 : 
    1581                 :     gfxFloat                   mAdjustedSize;
    1582                 : 
    1583                 :     float                      mFUnitsConvFactor; // conversion factor from font units to dev units
    1584                 : 
    1585                 :     // the AA setting requested for this font - may affect glyph bounds
    1586                 :     AntialiasOption            mAntialiasOption;
    1587                 : 
    1588                 :     // a copy of the font without antialiasing, if needed for separate
    1589                 :     // measurement by mathml code
    1590                 :     nsAutoPtr<gfxFont>         mNonAAFont;
    1591                 : 
    1592                 :     // we may switch between these shapers on the fly, based on the script
    1593                 :     // of the text run being shaped
    1594                 :     nsAutoPtr<gfxFontShaper>   mPlatformShaper;
    1595                 :     nsAutoPtr<gfxFontShaper>   mHarfBuzzShaper;
    1596                 : #ifdef MOZ_GRAPHITE
    1597                 :     nsAutoPtr<gfxFontShaper>   mGraphiteShaper;
    1598                 : #endif
    1599                 : 
    1600                 :     // Create a default platform text shaper for this font.
    1601                 :     // (TODO: This should become pure virtual once all font backends have
    1602                 :     // been updated.)
    1603               0 :     virtual void CreatePlatformShaper() { }
    1604                 : 
    1605                 :     // Helper for subclasses that want to initialize standard metrics from the
    1606                 :     // tables of sfnt (TrueType/OpenType) fonts.
    1607                 :     // This will use mFUnitsConvFactor if it is already set, else compute it
    1608                 :     // from mAdjustedSize and the unitsPerEm in the font's 'head' table.
    1609                 :     // Returns TRUE and sets mIsValid=TRUE if successful;
    1610                 :     // Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
    1611                 :     // Returns FALSE if the font does not appear to be an sfnt at all,
    1612                 :     // and should be handled (if possible) using other APIs.
    1613                 :     bool InitMetricsFromSfntTables(Metrics& aMetrics);
    1614                 : 
    1615                 :     // Helper to calculate various derived metrics from the results of
    1616                 :     // InitMetricsFromSfntTables or equivalent platform code
    1617                 :     void CalculateDerivedMetrics(Metrics& aMetrics);
    1618                 : 
    1619                 :     // some fonts have bad metrics, this method sanitize them.
    1620                 :     // if this font has bad underline offset, aIsBadUnderlineFont should be true.
    1621                 :     void SanitizeMetrics(gfxFont::Metrics *aMetrics, bool aIsBadUnderlineFont);
    1622                 : 
    1623                 :     // Bug 674909. When synthetic bolding text by drawing twice, need to
    1624                 :     // render using a pixel offset in device pixels, otherwise text
    1625                 :     // doesn't appear bolded, it appears as if a bad text shadow exists
    1626                 :     // when a non-identity transform exists.  Use an offset factor so that
    1627                 :     // the second draw occurs at a constant offset in device pixels.
    1628                 :     // This helper calculates the scale factor we need to apply to the
    1629                 :     // synthetic-bold offset.
    1630                 :     static double CalcXScale(gfxContext *aContext);
    1631                 : };
    1632                 : 
    1633                 : // proportion of ascent used for x-height, if unable to read value from font
    1634                 : #define DEFAULT_XHEIGHT_FACTOR 0.56f
    1635                 : 
    1636                 : /*
    1637                 :  * gfxShapedWord stores a list of zero or more glyphs for each character. For each
    1638                 :  * glyph we store the glyph ID, the advance, and possibly an xoffset and yoffset.
    1639                 :  * The idea is that a string is rendered by a loop that draws each glyph
    1640                 :  * at its designated offset from the current point, then advances the current
    1641                 :  * point by the glyph's advance in the direction of the textrun (LTR or RTL).
    1642                 :  * Each glyph advance is always rounded to the nearest appunit; this ensures
    1643                 :  * consistent results when dividing the text in a textrun into multiple text
    1644                 :  * frames (frame boundaries are always aligned to appunits). We optimize
    1645                 :  * for the case where a character has a single glyph and zero xoffset and yoffset,
    1646                 :  * and the glyph ID and advance are in a reasonable range so we can pack all
    1647                 :  * necessary data into 32 bits.
    1648                 :  *
    1649                 :  * This glyph data is copied into gfxTextRuns as needed from the cache of
    1650                 :  * ShapedWords associated with each gfxFont instance.
    1651                 :  *
    1652                 :  * gfxTextRun methods that measure or draw substrings will associate all the
    1653                 :  * glyphs in a cluster with the first character of the cluster; if that character
    1654                 :  * is in the substring, the glyphs will be measured or drawn, otherwise they
    1655                 :  * won't.
    1656                 :  */
    1657                 : class gfxShapedWord
    1658               0 : {
    1659                 : public:
    1660                 :     static const PRUint32 kMaxLength = 0x7fff;
    1661                 : 
    1662                 :     // Create a ShapedWord that can hold glyphs for aLength characters,
    1663                 :     // with mCharacterGlyphs sized appropriately.
    1664                 :     //
    1665                 :     // Returns null on allocation failure (does NOT use infallible alloc)
    1666                 :     // so caller must check for success.
    1667                 :     //
    1668                 :     // This does NOT perform shaping, so the returned word contains no
    1669                 :     // glyph data; the caller must call gfxFont::Shape() with appropriate
    1670                 :     // parameters to set up the glyphs.
    1671               0 :     static gfxShapedWord* Create(const PRUint8 *aText, PRUint32 aLength,
    1672                 :                                  PRInt32 aRunScript,
    1673                 :                                  PRInt32 aAppUnitsPerDevUnit,
    1674                 :                                  PRUint32 aFlags) {
    1675               0 :         NS_ASSERTION(aLength <= kMaxLength, "excessive length for gfxShapedWord!");
    1676                 : 
    1677                 :         // Compute size needed including the mCharacterGlyphs array
    1678                 :         // and a copy of the original text
    1679                 :         PRUint32 size =
    1680                 :             offsetof(gfxShapedWord, mCharacterGlyphs) +
    1681               0 :             aLength * (sizeof(CompressedGlyph) + sizeof(PRUint8));
    1682               0 :         void *storage = moz_malloc(size);
    1683               0 :         if (!storage) {
    1684               0 :             return nsnull;
    1685                 :         }
    1686                 : 
    1687                 :         // Construct in the pre-allocated storage, using placement new
    1688                 :         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
    1689               0 :                                            aAppUnitsPerDevUnit, aFlags);
    1690                 :     }
    1691                 : 
    1692               0 :     static gfxShapedWord* Create(const PRUnichar *aText, PRUint32 aLength,
    1693                 :                                  PRInt32 aRunScript,
    1694                 :                                  PRInt32 aAppUnitsPerDevUnit,
    1695                 :                                  PRUint32 aFlags) {
    1696               0 :         NS_ASSERTION(aLength <= kMaxLength, "excessive length for gfxShapedWord!");
    1697                 : 
    1698                 :         // In the 16-bit version of Create, if the TEXT_IS_8BIT flag is set,
    1699                 :         // then we convert the text to an 8-bit version and call the 8-bit
    1700                 :         // Create function instead.
    1701               0 :         if (aFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
    1702               0 :             nsCAutoString narrowText;
    1703               0 :             LossyAppendUTF16toASCII(nsDependentSubstring(aText, aLength),
    1704               0 :                                     narrowText);
    1705               0 :             return Create((const PRUint8*)(narrowText.BeginReading()),
    1706               0 :                           aLength, aRunScript, aAppUnitsPerDevUnit, aFlags);
    1707                 :         }
    1708                 : 
    1709                 :         PRUint32 size =
    1710                 :             offsetof(gfxShapedWord, mCharacterGlyphs) +
    1711               0 :             aLength * (sizeof(CompressedGlyph) + sizeof(PRUnichar));
    1712               0 :         void *storage = moz_malloc(size);
    1713               0 :         if (!storage) {
    1714               0 :             return nsnull;
    1715                 :         }
    1716                 : 
    1717                 :         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
    1718               0 :                                            aAppUnitsPerDevUnit, aFlags);
    1719                 :     }
    1720                 : 
    1721                 :     // Override operator delete to properly free the object that was
    1722                 :     // allocated via moz_malloc.
    1723               0 :     void operator delete(void* p) {
    1724               0 :         moz_free(p);
    1725               0 :     }
    1726                 : 
    1727                 :     /**
    1728                 :      * This class records the information associated with a character in the
    1729                 :      * input string. It's optimized for the case where there is one glyph
    1730                 :      * representing that character alone.
    1731                 :      * 
    1732                 :      * A character can have zero or more associated glyphs. Each glyph
    1733                 :      * has an advance width and an x and y offset.
    1734                 :      * A character may be the start of a cluster.
    1735                 :      * A character may be the start of a ligature group.
    1736                 :      * A character can be "missing", indicating that the system is unable
    1737                 :      * to render the character.
    1738                 :      * 
    1739                 :      * All characters in a ligature group conceptually share all the glyphs
    1740                 :      * associated with the characters in a group.
    1741                 :      */
    1742                 :     class CompressedGlyph {
    1743                 :     public:
    1744               0 :         CompressedGlyph() { mValue = 0; }
    1745                 : 
    1746                 :         enum {
    1747                 :             // Indicates that a cluster and ligature group starts at this
    1748                 :             // character; this character has a single glyph with a reasonable
    1749                 :             // advance and zero offsets. A "reasonable" advance
    1750                 :             // is one that fits in the available bits (currently 12) (specified
    1751                 :             // in appunits).
    1752                 :             FLAG_IS_SIMPLE_GLYPH  = 0x80000000U,
    1753                 : 
    1754                 :             // Indicates whether a linebreak is allowed before this character;
    1755                 :             // this is a two-bit field that holds a FLAG_BREAK_TYPE_xxx value
    1756                 :             // indicating the kind of linebreak (if any) allowed here.
    1757                 :             FLAGS_CAN_BREAK_BEFORE = 0x60000000U,
    1758                 : 
    1759                 :             FLAGS_CAN_BREAK_SHIFT = 29,
    1760                 :             FLAG_BREAK_TYPE_NONE   = 0,
    1761                 :             FLAG_BREAK_TYPE_NORMAL = 1,
    1762                 :             FLAG_BREAK_TYPE_HYPHEN = 2,
    1763                 : 
    1764                 :             FLAG_CHAR_IS_SPACE     = 0x10000000U,
    1765                 : 
    1766                 :             // The advance is stored in appunits
    1767                 :             ADVANCE_MASK  = 0x0FFF0000U,
    1768                 :             ADVANCE_SHIFT = 16,
    1769                 : 
    1770                 :             GLYPH_MASK = 0x0000FFFFU,
    1771                 : 
    1772                 :             // Non-simple glyphs may or may not have glyph data in the
    1773                 :             // corresponding mDetailedGlyphs entry. They have the following
    1774                 :             // flag bits:
    1775                 : 
    1776                 :             // When NOT set, indicates that this character corresponds to a
    1777                 :             // missing glyph and should be skipped (or possibly, render the character
    1778                 :             // Unicode value in some special way). If there are glyphs,
    1779                 :             // the mGlyphID is actually the UTF16 character code. The bit is
    1780                 :             // inverted so we can memset the array to zero to indicate all missing.
    1781                 :             FLAG_NOT_MISSING              = 0x01,
    1782                 :             FLAG_NOT_CLUSTER_START        = 0x02,
    1783                 :             FLAG_NOT_LIGATURE_GROUP_START = 0x04,
    1784                 : 
    1785                 :             FLAG_CHAR_IS_TAB              = 0x08,
    1786                 :             FLAG_CHAR_IS_NEWLINE          = 0x10,
    1787                 :             FLAG_CHAR_IS_LOW_SURROGATE    = 0x20,
    1788                 :             CHAR_IDENTITY_FLAGS_MASK      = 0x38,
    1789                 : 
    1790                 :             GLYPH_COUNT_MASK = 0x00FFFF00U,
    1791                 :             GLYPH_COUNT_SHIFT = 8
    1792                 :         };
    1793                 : 
    1794                 :         // "Simple glyphs" have a simple glyph ID, simple advance and their
    1795                 :         // x and y offsets are zero. Also the glyph extents do not overflow
    1796                 :         // the font-box defined by the font ascent, descent and glyph advance width.
    1797                 :         // These case is optimized to avoid storing DetailedGlyphs.
    1798                 : 
    1799                 :         // Returns true if the glyph ID aGlyph fits into the compressed representation
    1800               0 :         static bool IsSimpleGlyphID(PRUint32 aGlyph) {
    1801               0 :             return (aGlyph & GLYPH_MASK) == aGlyph;
    1802                 :         }
    1803                 :         // Returns true if the advance aAdvance fits into the compressed representation.
    1804                 :         // aAdvance is in appunits.
    1805               0 :         static bool IsSimpleAdvance(PRUint32 aAdvance) {
    1806               0 :             return (aAdvance & (ADVANCE_MASK >> ADVANCE_SHIFT)) == aAdvance;
    1807                 :         }
    1808                 : 
    1809               0 :         bool IsSimpleGlyph() const { return (mValue & FLAG_IS_SIMPLE_GLYPH) != 0; }
    1810               0 :         PRUint32 GetSimpleAdvance() const { return (mValue & ADVANCE_MASK) >> ADVANCE_SHIFT; }
    1811               0 :         PRUint32 GetSimpleGlyph() const { return mValue & GLYPH_MASK; }
    1812                 : 
    1813               0 :         bool IsMissing() const { return (mValue & (FLAG_NOT_MISSING|FLAG_IS_SIMPLE_GLYPH)) == 0; }
    1814               0 :         bool IsClusterStart() const {
    1815               0 :             return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_CLUSTER_START);
    1816                 :         }
    1817               0 :         bool IsLigatureGroupStart() const {
    1818               0 :             return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_LIGATURE_GROUP_START);
    1819                 :         }
    1820               0 :         bool IsLigatureContinuation() const {
    1821                 :             return (mValue & FLAG_IS_SIMPLE_GLYPH) == 0 &&
    1822                 :                 (mValue & (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING)) ==
    1823               0 :                     (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING);
    1824                 :         }
    1825                 : 
    1826                 :         // Return true if the original character was a normal (breakable,
    1827                 :         // trimmable) space (U+0020). Not true for other characters that
    1828                 :         // may happen to map to the space glyph (U+00A0).
    1829               0 :         bool CharIsSpace() const {
    1830               0 :             return (mValue & FLAG_CHAR_IS_SPACE) != 0;
    1831                 :         }
    1832                 : 
    1833                 :         bool CharIsTab() const {
    1834                 :             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_TAB) != 0;
    1835                 :         }
    1836                 :         bool CharIsNewline() const {
    1837                 :             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_NEWLINE) != 0;
    1838                 :         }
    1839                 :         bool CharIsLowSurrogate() const {
    1840                 :             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_LOW_SURROGATE) != 0;
    1841                 :         }
    1842                 : 
    1843               0 :         PRUint32 CharIdentityFlags() const {
    1844               0 :             return IsSimpleGlyph() ? 0 : (mValue & CHAR_IDENTITY_FLAGS_MASK);
    1845                 :         }
    1846                 : 
    1847               0 :         void SetClusterStart(bool aIsClusterStart) {
    1848               0 :             NS_ASSERTION(!IsSimpleGlyph(),
    1849                 :                          "can't call SetClusterStart on simple glyphs");
    1850               0 :             if (aIsClusterStart) {
    1851               0 :                 mValue &= ~FLAG_NOT_CLUSTER_START;
    1852                 :             } else {
    1853               0 :                 mValue |= FLAG_NOT_CLUSTER_START;
    1854                 :             }
    1855               0 :         }
    1856                 : 
    1857               0 :         PRUint8 CanBreakBefore() const {
    1858               0 :             return (mValue & FLAGS_CAN_BREAK_BEFORE) >> FLAGS_CAN_BREAK_SHIFT;
    1859                 :         }
    1860                 :         // Returns FLAGS_CAN_BREAK_BEFORE if the setting changed, 0 otherwise
    1861               0 :         PRUint32 SetCanBreakBefore(PRUint8 aCanBreakBefore) {
    1862               0 :             NS_ASSERTION(aCanBreakBefore <= 2,
    1863                 :                          "Bogus break-before value!");
    1864               0 :             PRUint32 breakMask = (PRUint32(aCanBreakBefore) << FLAGS_CAN_BREAK_SHIFT);
    1865               0 :             PRUint32 toggle = breakMask ^ (mValue & FLAGS_CAN_BREAK_BEFORE);
    1866               0 :             mValue ^= toggle;
    1867               0 :             return toggle;
    1868                 :         }
    1869                 : 
    1870               0 :         CompressedGlyph& SetSimpleGlyph(PRUint32 aAdvanceAppUnits, PRUint32 aGlyph) {
    1871               0 :             NS_ASSERTION(IsSimpleAdvance(aAdvanceAppUnits), "Advance overflow");
    1872               0 :             NS_ASSERTION(IsSimpleGlyphID(aGlyph), "Glyph overflow");
    1873               0 :             NS_ASSERTION(!CharIdentityFlags(), "Char identity flags lost");
    1874                 :             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) |
    1875                 :                 FLAG_IS_SIMPLE_GLYPH |
    1876               0 :                 (aAdvanceAppUnits << ADVANCE_SHIFT) | aGlyph;
    1877               0 :             return *this;
    1878                 :         }
    1879               0 :         CompressedGlyph& SetComplex(bool aClusterStart, bool aLigatureStart,
    1880                 :                 PRUint32 aGlyphCount) {
    1881                 :             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) |
    1882                 :                 FLAG_NOT_MISSING |
    1883               0 :                 CharIdentityFlags() |
    1884                 :                 (aClusterStart ? 0 : FLAG_NOT_CLUSTER_START) |
    1885                 :                 (aLigatureStart ? 0 : FLAG_NOT_LIGATURE_GROUP_START) |
    1886               0 :                 (aGlyphCount << GLYPH_COUNT_SHIFT);
    1887               0 :             return *this;
    1888                 :         }
    1889                 :         /**
    1890                 :          * Missing glyphs are treated as ligature group starts; don't mess with
    1891                 :          * the cluster-start flag (see bugs 618870 and 619286).
    1892                 :          */
    1893               0 :         CompressedGlyph& SetMissing(PRUint32 aGlyphCount) {
    1894                 :             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_NOT_CLUSTER_START |
    1895                 :                                 FLAG_CHAR_IS_SPACE)) |
    1896               0 :                 CharIdentityFlags() |
    1897               0 :                 (aGlyphCount << GLYPH_COUNT_SHIFT);
    1898               0 :             return *this;
    1899                 :         }
    1900               0 :         PRUint32 GetGlyphCount() const {
    1901               0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
    1902               0 :             return (mValue & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT;
    1903                 :         }
    1904                 : 
    1905               0 :         void SetIsSpace() {
    1906               0 :             mValue |= FLAG_CHAR_IS_SPACE;
    1907               0 :         }
    1908               0 :         void SetIsTab() {
    1909               0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
    1910               0 :             mValue |= FLAG_CHAR_IS_TAB;
    1911               0 :         }
    1912               0 :         void SetIsNewline() {
    1913               0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
    1914               0 :             mValue |= FLAG_CHAR_IS_NEWLINE;
    1915               0 :         }
    1916               0 :         void SetIsLowSurrogate() {
    1917               0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
    1918               0 :             mValue |= FLAG_CHAR_IS_LOW_SURROGATE;
    1919               0 :         }
    1920                 : 
    1921                 :     private:
    1922                 :         PRUint32 mValue;
    1923                 :     };
    1924                 : 
    1925                 :     /**
    1926                 :      * When the glyphs for a character don't fit into a CompressedGlyph record
    1927                 :      * in SimpleGlyph format, we use an array of DetailedGlyphs instead.
    1928                 :      */
    1929               0 :     struct DetailedGlyph {
    1930                 :         /** The glyphID, or the Unicode character
    1931                 :          * if this is a missing glyph */
    1932                 :         PRUint32 mGlyphID;
    1933                 :         /** The advance, x-offset and y-offset of the glyph, in appunits
    1934                 :          *  mAdvance is in the text direction (RTL or LTR)
    1935                 :          *  mXOffset is always from left to right
    1936                 :          *  mYOffset is always from top to bottom */   
    1937                 :         PRInt32  mAdvance;
    1938                 :         float    mXOffset, mYOffset;
    1939                 :     };
    1940                 : 
    1941               0 :     bool IsClusterStart(PRUint32 aPos) {
    1942               0 :         NS_ASSERTION(aPos < Length(), "aPos out of range");
    1943               0 :         return mCharacterGlyphs[aPos].IsClusterStart();
    1944                 :     }
    1945                 : 
    1946                 :     bool IsLigatureGroupStart(PRUint32 aPos) {
    1947                 :         NS_ASSERTION(aPos < Length(), "aPos out of range");
    1948                 :         return mCharacterGlyphs[aPos].IsLigatureGroupStart();
    1949                 :     }
    1950                 : 
    1951               0 :     PRUint32 Length() const {
    1952               0 :         return mLength;
    1953                 :     }
    1954                 : 
    1955               0 :     const PRUint8* Text8Bit() const {
    1956               0 :         NS_ASSERTION(TextIs8Bit(), "invalid use of Text8Bit()");
    1957               0 :         return reinterpret_cast<const PRUint8*>(&mCharacterGlyphs[Length()]);
    1958                 :     }
    1959                 : 
    1960               0 :     const PRUnichar* TextUnicode() const {
    1961               0 :         NS_ASSERTION(!TextIs8Bit(), "invalid use of TextUnicode()");
    1962               0 :         return reinterpret_cast<const PRUnichar*>(&mCharacterGlyphs[Length()]);
    1963                 :     }
    1964                 : 
    1965               0 :     PRUnichar GetCharAt(PRUint32 aOffset) const {
    1966               0 :         NS_ASSERTION(aOffset < Length(), "aOffset out of range");
    1967               0 :         return TextIs8Bit() ?
    1968               0 :             PRUnichar(Text8Bit()[aOffset]) : TextUnicode()[aOffset];
    1969                 :     }
    1970                 : 
    1971               0 :     PRUint32 Flags() const {
    1972               0 :         return mFlags;
    1973                 :     }
    1974                 : 
    1975               0 :     bool IsRightToLeft() const {
    1976               0 :         return (Flags() & gfxTextRunFactory::TEXT_IS_RTL) != 0;
    1977                 :     }
    1978                 : 
    1979                 :     float GetDirection() const {
    1980                 :         return IsRightToLeft() ? -1.0 : 1.0;
    1981                 :     }
    1982                 : 
    1983               0 :     bool DisableLigatures() const {
    1984               0 :         return (Flags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) != 0;
    1985                 :     }
    1986                 : 
    1987               0 :     bool TextIs8Bit() const {
    1988               0 :         return (Flags() & gfxTextRunFactory::TEXT_IS_8BIT) != 0;
    1989                 :     }
    1990                 : 
    1991               0 :     PRInt32 Script() const {
    1992               0 :         return mScript;
    1993                 :     }
    1994                 : 
    1995               0 :     PRInt32 AppUnitsPerDevUnit() const {
    1996               0 :         return mAppUnitsPerDevUnit;
    1997                 :     }
    1998                 : 
    1999               0 :     void ResetAge() {
    2000               0 :         mAgeCounter = 0;
    2001               0 :     }
    2002               0 :     PRUint32 IncrementAge() {
    2003               0 :         return ++mAgeCounter;
    2004                 :     }
    2005                 : 
    2006               0 :     void SetSimpleGlyph(PRUint32 aCharIndex, CompressedGlyph aGlyph) {
    2007               0 :         NS_ASSERTION(aGlyph.IsSimpleGlyph(), "Should be a simple glyph here");
    2008               0 :         NS_ASSERTION(mCharacterGlyphs, "mCharacterGlyphs pointer is null!");
    2009               0 :         mCharacterGlyphs[aCharIndex] = aGlyph;
    2010               0 :     }
    2011                 : 
    2012                 :     void SetGlyphs(PRUint32 aCharIndex, CompressedGlyph aGlyph,
    2013                 :                    const DetailedGlyph *aGlyphs);
    2014                 : 
    2015                 :     void SetMissingGlyph(PRUint32 aIndex, PRUint32 aChar, gfxFont *aFont);
    2016                 : 
    2017               0 :     void SetIsSpace(PRUint32 aIndex) {
    2018               0 :         mCharacterGlyphs[aIndex].SetIsSpace();
    2019               0 :     }
    2020                 : 
    2021               0 :     void SetIsLowSurrogate(PRUint32 aIndex) {
    2022               0 :         SetGlyphs(aIndex, CompressedGlyph().SetComplex(false, false, 0), nsnull);
    2023               0 :         mCharacterGlyphs[aIndex].SetIsLowSurrogate();
    2024               0 :     }
    2025                 : 
    2026                 :     bool FilterIfIgnorable(PRUint32 aIndex);
    2027                 : 
    2028               0 :     const CompressedGlyph *GetCharacterGlyphs() const {
    2029               0 :         return &mCharacterGlyphs[0];
    2030                 :     }
    2031                 : 
    2032               0 :     bool HasDetailedGlyphs() const {
    2033               0 :         return mDetailedGlyphs != nsnull;
    2034                 :     }
    2035                 : 
    2036                 :     // NOTE that this must not be called for a character offset that does
    2037                 :     // not have any DetailedGlyph records; callers must have verified that
    2038                 :     // mCharacterGlyphs[aCharIndex].GetGlyphCount() is greater than zero.
    2039               0 :     DetailedGlyph *GetDetailedGlyphs(PRUint32 aCharIndex) const {
    2040               0 :         NS_ASSERTION(HasDetailedGlyphs() &&
    2041                 :                      !mCharacterGlyphs[aCharIndex].IsSimpleGlyph() &&
    2042                 :                      mCharacterGlyphs[aCharIndex].GetGlyphCount() > 0,
    2043                 :                      "invalid use of GetDetailedGlyphs; check the caller!");
    2044               0 :         return mDetailedGlyphs->Get(aCharIndex);
    2045                 :     }
    2046                 : 
    2047                 :     void AdjustAdvancesForSyntheticBold(float aSynBoldOffset);
    2048                 : 
    2049                 :     // this is a public static method in order to make it available
    2050                 :     // for gfxTextRun to use directly on its own CompressedGlyph array,
    2051                 :     // in addition to the use within ShapedWord
    2052                 :     static void
    2053                 :     SetupClusterBoundaries(CompressedGlyph *aGlyphs,
    2054                 :                            const PRUnichar *aString, PRUint32 aLength);
    2055                 : 
    2056                 : private:
    2057                 :     // so that gfxTextRun can share our DetailedGlyphStore class
    2058                 :     friend class gfxTextRun;
    2059                 : 
    2060                 :     // Construct storage for a ShapedWord, ready to receive glyph data
    2061               0 :     gfxShapedWord(const PRUint8 *aText, PRUint32 aLength,
    2062                 :                   PRInt32 aRunScript, PRInt32 aAppUnitsPerDevUnit,
    2063                 :                   PRUint32 aFlags)
    2064                 :         : mLength(aLength)
    2065                 :         , mFlags(aFlags | gfxTextRunFactory::TEXT_IS_8BIT)
    2066                 :         , mAppUnitsPerDevUnit(aAppUnitsPerDevUnit)
    2067                 :         , mScript(aRunScript)
    2068               0 :         , mAgeCounter(0)
    2069                 :     {
    2070               0 :         memset(mCharacterGlyphs, 0, aLength * sizeof(CompressedGlyph));
    2071               0 :         PRUint8 *text = reinterpret_cast<PRUint8*>(&mCharacterGlyphs[aLength]);
    2072               0 :         memcpy(text, aText, aLength * sizeof(PRUint8));
    2073               0 :     }
    2074                 : 
    2075               0 :     gfxShapedWord(const PRUnichar *aText, PRUint32 aLength,
    2076                 :                   PRInt32 aRunScript, PRInt32 aAppUnitsPerDevUnit,
    2077                 :                   PRUint32 aFlags)
    2078                 :         : mLength(aLength)
    2079                 :         , mFlags(aFlags)
    2080                 :         , mAppUnitsPerDevUnit(aAppUnitsPerDevUnit)
    2081                 :         , mScript(aRunScript)
    2082               0 :         , mAgeCounter(0)
    2083                 :     {
    2084               0 :         memset(mCharacterGlyphs, 0, aLength * sizeof(CompressedGlyph));
    2085               0 :         PRUnichar *text = reinterpret_cast<PRUnichar*>(&mCharacterGlyphs[aLength]);
    2086               0 :         memcpy(text, aText, aLength * sizeof(PRUnichar));
    2087               0 :         SetupClusterBoundaries(&mCharacterGlyphs[0], aText, aLength);
    2088               0 :     }
    2089                 : 
    2090                 :     // Allocate aCount DetailedGlyphs for the given index
    2091                 :     DetailedGlyph *AllocateDetailedGlyphs(PRUint32 aCharIndex,
    2092                 :                                           PRUint32 aCount);
    2093                 : 
    2094                 :     // For characters whose glyph data does not fit the "simple" glyph criteria
    2095                 :     // in CompressedGlyph, we use a sorted array to store the association
    2096                 :     // between the source character offset and an index into an array 
    2097                 :     // DetailedGlyphs. The CompressedGlyph record includes a count of
    2098                 :     // the number of DetailedGlyph records that belong to the character,
    2099                 :     // starting at the given index.
    2100               0 :     class DetailedGlyphStore {
    2101                 :     public:
    2102               0 :         DetailedGlyphStore()
    2103               0 :             : mLastUsed(0)
    2104               0 :         { }
    2105                 : 
    2106                 :         // This is optimized for the most common calling patterns:
    2107                 :         // we rarely need random access to the records, access is most commonly
    2108                 :         // sequential through the textRun, so we record the last-used index
    2109                 :         // and check whether the caller wants the same record again, or the
    2110                 :         // next; if not, it's most likely we're starting over from the start
    2111                 :         // of the run, so we check the first entry before resorting to binary
    2112                 :         // search as a last resort.
    2113                 :         // NOTE that this must not be called for a character offset that does
    2114                 :         // not have any DetailedGlyph records; callers must have verified that
    2115                 :         // mCharacterGlyphs[aOffset].GetGlyphCount() is greater than zero
    2116                 :         // before calling this, otherwise the assertions here will fire (in a
    2117                 :         // debug build), and we'll probably crash.
    2118               0 :         DetailedGlyph* Get(PRUint32 aOffset) {
    2119               0 :             NS_ASSERTION(mOffsetToIndex.Length() > 0,
    2120                 :                          "no detailed glyph records!");
    2121               0 :             DetailedGlyph* details = mDetails.Elements();
    2122                 :             // check common cases (fwd iteration, initial entry, etc) first
    2123               0 :             if (mLastUsed < mOffsetToIndex.Length() - 1 &&
    2124               0 :                 aOffset == mOffsetToIndex[mLastUsed + 1].mOffset) {
    2125               0 :                 ++mLastUsed;
    2126               0 :             } else if (aOffset == mOffsetToIndex[0].mOffset) {
    2127               0 :                 mLastUsed = 0;
    2128               0 :             } else if (aOffset == mOffsetToIndex[mLastUsed].mOffset) {
    2129                 :                 // do nothing
    2130               0 :             } else if (mLastUsed > 0 &&
    2131               0 :                        aOffset == mOffsetToIndex[mLastUsed - 1].mOffset) {
    2132               0 :                 --mLastUsed;
    2133                 :             } else {
    2134                 :                 mLastUsed =
    2135               0 :                     mOffsetToIndex.BinaryIndexOf(aOffset, CompareToOffset());
    2136                 :             }
    2137               0 :             NS_ASSERTION(mLastUsed != nsTArray<DGRec>::NoIndex,
    2138                 :                          "detailed glyph record missing!");
    2139               0 :             return details + mOffsetToIndex[mLastUsed].mIndex;
    2140                 :         }
    2141                 : 
    2142               0 :         DetailedGlyph* Allocate(PRUint32 aOffset, PRUint32 aCount) {
    2143               0 :             PRUint32 detailIndex = mDetails.Length();
    2144               0 :             DetailedGlyph *details = mDetails.AppendElements(aCount);
    2145               0 :             if (!details) {
    2146               0 :                 return nsnull;
    2147                 :             }
    2148                 :             // We normally set up glyph records sequentially, so the common case
    2149                 :             // here is to append new records to the mOffsetToIndex array;
    2150                 :             // test for that before falling back to the InsertElementSorted
    2151                 :             // method.
    2152               0 :             if (mOffsetToIndex.Length() == 0 ||
    2153               0 :                 aOffset > mOffsetToIndex[mOffsetToIndex.Length() - 1].mOffset) {
    2154               0 :                 if (!mOffsetToIndex.AppendElement(DGRec(aOffset, detailIndex))) {
    2155               0 :                     return nsnull;
    2156                 :                 }
    2157                 :             } else {
    2158               0 :                 if (!mOffsetToIndex.InsertElementSorted(DGRec(aOffset, detailIndex),
    2159               0 :                                                         CompareRecordOffsets())) {
    2160               0 :                     return nsnull;
    2161                 :                 }
    2162                 :             }
    2163               0 :             return details;
    2164                 :         }
    2165                 : 
    2166               0 :         size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) {
    2167               0 :             return aMallocSizeOf(this) +
    2168               0 :                 mDetails.SizeOfExcludingThis(aMallocSizeOf) +
    2169               0 :                 mOffsetToIndex.SizeOfExcludingThis(aMallocSizeOf);
    2170                 :         }
    2171                 : 
    2172                 :     private:
    2173               0 :         struct DGRec {
    2174               0 :             DGRec(const PRUint32& aOffset, const PRUint32& aIndex)
    2175               0 :                 : mOffset(aOffset), mIndex(aIndex) { }
    2176                 :             PRUint32 mOffset; // source character offset in the textrun
    2177                 :             PRUint32 mIndex;  // index where this char's DetailedGlyphs begin
    2178                 :         };
    2179                 : 
    2180                 :         struct CompareToOffset {
    2181               0 :             bool Equals(const DGRec& a, const PRUint32& b) const {
    2182               0 :                 return a.mOffset == b;
    2183                 :             }
    2184               0 :             bool LessThan(const DGRec& a, const PRUint32& b) const {
    2185               0 :                 return a.mOffset < b;
    2186                 :             }
    2187                 :         };
    2188                 : 
    2189                 :         struct CompareRecordOffsets {
    2190               0 :             bool Equals(const DGRec& a, const DGRec& b) const {
    2191               0 :                 return a.mOffset == b.mOffset;
    2192                 :             }
    2193               0 :             bool LessThan(const DGRec& a, const DGRec& b) const {
    2194               0 :                 return a.mOffset < b.mOffset;
    2195                 :             }
    2196                 :         };
    2197                 : 
    2198                 :         // Concatenated array of all the DetailedGlyph records needed for the
    2199                 :         // textRun; individual character offsets are associated with indexes
    2200                 :         // into this array via the mOffsetToIndex table.
    2201                 :         nsTArray<DetailedGlyph>     mDetails;
    2202                 : 
    2203                 :         // For each character offset that needs DetailedGlyphs, we record the
    2204                 :         // index in mDetails where the list of glyphs begins. This array is
    2205                 :         // sorted by mOffset.
    2206                 :         nsTArray<DGRec>             mOffsetToIndex;
    2207                 : 
    2208                 :         // Records the most recently used index into mOffsetToIndex, so that
    2209                 :         // we can support sequential access more quickly than just doing
    2210                 :         // a binary search each time.
    2211                 :         nsTArray<DGRec>::index_type mLastUsed;
    2212                 :     };
    2213                 : 
    2214                 :     nsAutoPtr<DetailedGlyphStore>   mDetailedGlyphs;
    2215                 : 
    2216                 :     // Number of PRUnichar characters and CompressedGlyph glyph records;
    2217                 :     // note that gfx font code will never attempt to create a ShapedWord
    2218                 :     // with a huge number of characters, so we could limit this to 16 bits
    2219                 :     // to minimize memory usage for large numbers of cached words.
    2220                 :     PRUint32                        mLength;
    2221                 : 
    2222                 :     PRUint32                        mFlags;
    2223                 : 
    2224                 :     PRInt32                         mAppUnitsPerDevUnit;
    2225                 :     PRInt32                         mScript;
    2226                 : 
    2227                 :     PRUint32                        mAgeCounter;
    2228                 : 
    2229                 :     // The mCharacterGlyphs array is actually a variable-size member;
    2230                 :     // when the ShapedWord is created, its size will be increased as necessary
    2231                 :     // to allow the proper number of glyphs to be stored.
    2232                 :     // The original text, in either 8-bit or 16-bit form, will be stored
    2233                 :     // immediately following the CompressedGlyphs.
    2234                 :     CompressedGlyph                 mCharacterGlyphs[1];
    2235                 : };
    2236                 : 
    2237                 : /**
    2238                 :  * gfxTextRun is an abstraction for drawing and measuring substrings of a run
    2239                 :  * of text. It stores runs of positioned glyph data, each run having a single
    2240                 :  * gfxFont. The glyphs are associated with a string of source text, and the
    2241                 :  * gfxTextRun APIs take parameters that are offsets into that source text.
    2242                 :  * 
    2243                 :  * gfxTextRuns are not refcounted. They should be deleted when no longer required.
    2244                 :  * 
    2245                 :  * gfxTextRuns are mostly immutable. The only things that can change are
    2246                 :  * inter-cluster spacing and line break placement. Spacing is always obtained
    2247                 :  * lazily by methods that need it, it is not cached. Line breaks are stored
    2248                 :  * persistently (insofar as they affect the shaping of glyphs; gfxTextRun does
    2249                 :  * not actually do anything to explicitly account for line breaks). Initially
    2250                 :  * there are no line breaks. The textrun can record line breaks before or after
    2251                 :  * any given cluster. (Line breaks specified inside clusters are ignored.)
    2252                 :  * 
    2253                 :  * It is important that zero-length substrings are handled correctly. This will
    2254                 :  * be on the test!
    2255                 :  */
    2256                 : class THEBES_API gfxTextRun {
    2257                 : public:
    2258                 :     // we use the same glyph storage as gfxShapedWord, to facilitate copying
    2259                 :     // glyph data from shaped words into text runs as needed
    2260                 :     typedef gfxShapedWord::CompressedGlyph    CompressedGlyph;
    2261                 :     typedef gfxShapedWord::DetailedGlyph      DetailedGlyph;
    2262                 :     typedef gfxShapedWord::DetailedGlyphStore DetailedGlyphStore;
    2263                 : 
    2264                 :     // Override operator delete to properly free the object that was
    2265                 :     // allocated via moz_malloc.
    2266               0 :     void operator delete(void* p) {
    2267               0 :         moz_free(p);
    2268               0 :     }
    2269                 : 
    2270                 :     virtual ~gfxTextRun();
    2271                 : 
    2272                 :     typedef gfxFont::RunMetrics Metrics;
    2273                 : 
    2274                 :     // Public textrun API for general use
    2275                 : 
    2276               0 :     bool IsClusterStart(PRUint32 aPos) {
    2277               0 :         NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
    2278               0 :         return mCharacterGlyphs[aPos].IsClusterStart();
    2279                 :     }
    2280                 :     bool IsLigatureGroupStart(PRUint32 aPos) {
    2281                 :         NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
    2282                 :         return mCharacterGlyphs[aPos].IsLigatureGroupStart();
    2283                 :     }
    2284                 :     bool CanBreakLineBefore(PRUint32 aPos) {
    2285                 :         NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
    2286                 :         return mCharacterGlyphs[aPos].CanBreakBefore() ==
    2287                 :             CompressedGlyph::FLAG_BREAK_TYPE_NORMAL;
    2288                 :     }
    2289                 :     bool CanHyphenateBefore(PRUint32 aPos) {
    2290                 :         NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
    2291                 :         return mCharacterGlyphs[aPos].CanBreakBefore() ==
    2292                 :             CompressedGlyph::FLAG_BREAK_TYPE_HYPHEN;
    2293                 :     }
    2294                 : 
    2295                 :     bool CharIsSpace(PRUint32 aPos) {
    2296                 :         NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
    2297                 :         return mCharacterGlyphs[aPos].CharIsSpace();
    2298                 :     }
    2299                 :     bool CharIsTab(PRUint32 aPos) {
    2300                 :         NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
    2301                 :         return mCharacterGlyphs[aPos].CharIsTab();
    2302                 :     }
    2303                 :     bool CharIsNewline(PRUint32 aPos) {
    2304                 :         NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
    2305                 :         return mCharacterGlyphs[aPos].CharIsNewline();
    2306                 :     }
    2307                 :     bool CharIsLowSurrogate(PRUint32 aPos) {
    2308                 :         NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
    2309                 :         return mCharacterGlyphs[aPos].CharIsLowSurrogate();
    2310                 :     }
    2311                 : 
    2312               0 :     PRUint32 GetLength() { return mCharacterCount; }
    2313                 : 
    2314                 :     // All PRUint32 aStart, PRUint32 aLength ranges below are restricted to
    2315                 :     // grapheme cluster boundaries! All offsets are in terms of the string
    2316                 :     // passed into MakeTextRun.
    2317                 :     
    2318                 :     // All coordinates are in layout/app units
    2319                 : 
    2320                 :     /**
    2321                 :      * Set the potential linebreaks for a substring of the textrun. These are
    2322                 :      * the "allow break before" points. Initially, there are no potential
    2323                 :      * linebreaks.
    2324                 :      * 
    2325                 :      * This can change glyphs and/or geometry! Some textruns' shapes
    2326                 :      * depend on potential line breaks (e.g., title-case-converting textruns).
    2327                 :      * This function is virtual so that those textruns can reshape themselves.
    2328                 :      * 
    2329                 :      * @return true if this changed the linebreaks, false if the new line
    2330                 :      * breaks are the same as the old
    2331                 :      */
    2332                 :     virtual bool SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
    2333                 :                                           PRUint8 *aBreakBefore,
    2334                 :                                           gfxContext *aRefContext);
    2335                 : 
    2336                 :     /**
    2337                 :      * Layout provides PropertyProvider objects. These allow detection of
    2338                 :      * potential line break points and computation of spacing. We pass the data
    2339                 :      * this way to allow lazy data acquisition; for example BreakAndMeasureText
    2340                 :      * will want to only ask for properties of text it's actually looking at.
    2341                 :      * 
    2342                 :      * NOTE that requested spacing may not actually be applied, if the textrun
    2343                 :      * is unable to apply it in some context. Exception: spacing around a
    2344                 :      * whitespace character MUST always be applied.
    2345                 :      */
    2346                 :     class PropertyProvider {
    2347                 :     public:
    2348                 :         // Detect hyphenation break opportunities in the given range; breaks
    2349                 :         // not at cluster boundaries will be ignored.
    2350                 :         virtual void GetHyphenationBreaks(PRUint32 aStart, PRUint32 aLength,
    2351                 :                                           bool *aBreakBefore) = 0;
    2352                 : 
    2353                 :         // Returns the provider's hyphenation setting, so callers can decide
    2354                 :         // whether it is necessary to call GetHyphenationBreaks.
    2355                 :         // Result is an NS_STYLE_HYPHENS_* value.
    2356                 :         virtual PRInt8 GetHyphensOption() = 0;
    2357                 : 
    2358                 :         // Returns the extra width that will be consumed by a hyphen. This should
    2359                 :         // be constant for a given textrun.
    2360                 :         virtual gfxFloat GetHyphenWidth() = 0;
    2361                 : 
    2362                 :         typedef gfxFont::Spacing Spacing;
    2363                 : 
    2364                 :         /**
    2365                 :          * Get the spacing around the indicated characters. Spacing must be zero
    2366                 :          * inside clusters. In other words, if character i is not
    2367                 :          * CLUSTER_START, then character i-1 must have zero after-spacing and
    2368                 :          * character i must have zero before-spacing.
    2369                 :          */
    2370                 :         virtual void GetSpacing(PRUint32 aStart, PRUint32 aLength,
    2371                 :                                 Spacing *aSpacing) = 0;
    2372                 :     };
    2373                 : 
    2374                 :     class ClusterIterator {
    2375                 :     public:
    2376                 :         ClusterIterator(gfxTextRun *aTextRun);
    2377                 : 
    2378                 :         void Reset();
    2379                 : 
    2380                 :         bool NextCluster();
    2381                 : 
    2382                 :         PRUint32 Position() const {
    2383                 :             return mCurrentChar;
    2384                 :         }
    2385                 : 
    2386                 :         PRUint32 ClusterLength() const;
    2387                 : 
    2388                 :         gfxFloat ClusterAdvance(PropertyProvider *aProvider) const;
    2389                 : 
    2390                 :     private:
    2391                 :         gfxTextRun *mTextRun;
    2392                 :         PRUint32    mCurrentChar;
    2393                 :     };
    2394                 : 
    2395                 :     /**
    2396                 :      * Draws a substring. Uses only GetSpacing from aBreakProvider.
    2397                 :      * The provided point is the baseline origin on the left of the string
    2398                 :      * for LTR, on the right of the string for RTL.
    2399                 :      * @param aAdvanceWidth if non-null, the advance width of the substring
    2400                 :      * is returned here.
    2401                 :      * 
    2402                 :      * Drawing should respect advance widths in the sense that for LTR runs,
    2403                 :      * Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by
    2404                 :      * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1 + length1, length2,
    2405                 :      *      dirty, &provider, nsnull) should have the same effect as
    2406                 :      * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
    2407                 :      * For RTL runs the rule is:
    2408                 :      * Draw(ctx, pt, offset1 + length1, length2, dirty, &provider, &advance) followed by
    2409                 :      * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1, length1,
    2410                 :      *      dirty, &provider, nsnull) should have the same effect as
    2411                 :      * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
    2412                 :      * 
    2413                 :      * Glyphs should be drawn in logical content order, which can be significant
    2414                 :      * if they overlap (perhaps due to negative spacing).
    2415                 :      */
    2416                 :     void Draw(gfxContext *aContext, gfxPoint aPt,
    2417                 :               gfxFont::DrawMode aDrawMode,
    2418                 :               PRUint32 aStart, PRUint32 aLength,
    2419                 :               PropertyProvider *aProvider,
    2420                 :               gfxFloat *aAdvanceWidth, gfxPattern *aStrokePattern);
    2421                 : 
    2422                 :     /**
    2423                 :      * Computes the ReflowMetrics for a substring.
    2424                 :      * Uses GetSpacing from aBreakProvider.
    2425                 :      * @param aBoundingBoxType which kind of bounding box (loose/tight)
    2426                 :      */
    2427                 :     Metrics MeasureText(PRUint32 aStart, PRUint32 aLength,
    2428                 :                         gfxFont::BoundingBoxType aBoundingBoxType,
    2429                 :                         gfxContext *aRefContextForTightBoundingBox,
    2430                 :                         PropertyProvider *aProvider);
    2431                 : 
    2432                 :     /**
    2433                 :      * Computes just the advance width for a substring.
    2434                 :      * Uses GetSpacing from aBreakProvider.
    2435                 :      */
    2436                 :     gfxFloat GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
    2437                 :                              PropertyProvider *aProvider);
    2438                 : 
    2439                 :     /**
    2440                 :      * Clear all stored line breaks for the given range (both before and after),
    2441                 :      * and then set the line-break state before aStart to aBreakBefore and
    2442                 :      * after the last cluster to aBreakAfter.
    2443                 :      * 
    2444                 :      * We require that before and after line breaks be consistent. For clusters
    2445                 :      * i and i+1, we require that if there is a break after cluster i, a break
    2446                 :      * will be specified before cluster i+1. This may be temporarily violated
    2447                 :      * (e.g. after reflowing line L and before reflowing line L+1); to handle
    2448                 :      * these temporary violations, we say that there is a break betwen i and i+1
    2449                 :      * if a break is specified after i OR a break is specified before i+1.
    2450                 :      * 
    2451                 :      * This can change textrun geometry! The existence of a linebreak can affect
    2452                 :      * the advance width of the cluster before the break (when kerning) or the
    2453                 :      * geometry of one cluster before the break or any number of clusters
    2454                 :      * after the break. (The one-cluster-before-the-break limit is somewhat
    2455                 :      * arbitrary; if some scripts require breaking it, then we need to
    2456                 :      * alter nsTextFrame::TrimTrailingWhitespace, perhaps drastically becase
    2457                 :      * it could affect the layout of frames before it...)
    2458                 :      * 
    2459                 :      * We return true if glyphs or geometry changed, false otherwise. This
    2460                 :      * function is virtual so that gfxTextRun subclasses can reshape
    2461                 :      * properly.
    2462                 :      * 
    2463                 :      * @param aAdvanceWidthDelta if non-null, returns the change in advance
    2464                 :      * width of the given range.
    2465                 :      */
    2466                 :     virtual bool SetLineBreaks(PRUint32 aStart, PRUint32 aLength,
    2467                 :                                  bool aLineBreakBefore, bool aLineBreakAfter,
    2468                 :                                  gfxFloat *aAdvanceWidthDelta,
    2469                 :                                  gfxContext *aRefContext);
    2470                 : 
    2471                 :     /**
    2472                 :      * Finds the longest substring that will fit into the given width.
    2473                 :      * Uses GetHyphenationBreaks and GetSpacing from aBreakProvider.
    2474                 :      * Guarantees the following:
    2475                 :      * -- 0 <= result <= aMaxLength
    2476                 :      * -- result is the maximal value of N such that either
    2477                 :      *       N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
    2478                 :      *   OR  N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
    2479                 :      *   OR  N == aMaxLength && GetAdvanceWidth(aStart, N) <= aWidth
    2480                 :      * where GetAdvanceWidth assumes the effect of
    2481                 :      * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
    2482                 :      * -- if no such N exists, then result is the smallest N such that
    2483                 :      *       N < aMaxLength && line break at N
    2484                 :      *   OR  N < aMaxLength && hyphen break at N
    2485                 :      *   OR  N == aMaxLength
    2486                 :      *
    2487                 :      * The call has the effect of
    2488                 :      * SetLineBreaks(aStart, result, aLineBreakBefore, result < aMaxLength, aProvider)
    2489                 :      * and the returned metrics and the invariants above reflect this.
    2490                 :      *
    2491                 :      * @param aMaxLength this can be PR_UINT32_MAX, in which case the length used
    2492                 :      * is up to the end of the string
    2493                 :      * @param aLineBreakBefore set to true if and only if there is an actual
    2494                 :      * line break at the start of this string.
    2495                 :      * @param aSuppressInitialBreak if true, then we assume there is no possible
    2496                 :      * linebreak before aStart. If false, then we will check the internal
    2497                 :      * line break opportunity state before deciding whether to return 0 as the
    2498                 :      * character to break before.
    2499                 :      * @param aTrimWhitespace if non-null, then we allow a trailing run of
    2500                 :      * spaces to be trimmed; the width of the space(s) will not be included in
    2501                 :      * the measured string width for comparison with the limit aWidth, and
    2502                 :      * trimmed spaces will not be included in returned metrics. The width
    2503                 :      * of the trimmed spaces will be returned in aTrimWhitespace.
    2504                 :      * Trimmed spaces are still counted in the "characters fit" result.
    2505                 :      * @param aMetrics if non-null, we fill this in for the returned substring.
    2506                 :      * If a hyphenation break was used, the hyphen is NOT included in the returned metrics.
    2507                 :      * @param aBoundingBoxType whether to make the bounding box in aMetrics tight
    2508                 :      * @param aRefContextForTightBoundingBox a reference context to get the
    2509                 :      * tight bounding box, if requested
    2510                 :      * @param aUsedHyphenation if non-null, records if we selected a hyphenation break
    2511                 :      * @param aLastBreak if non-null and result is aMaxLength, we set this to
    2512                 :      * the maximal N such that
    2513                 :      *       N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
    2514                 :      *   OR  N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
    2515                 :      * or PR_UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
    2516                 :      * the effect of
    2517                 :      * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
    2518                 :      *
    2519                 :      * @param aCanWordWrap true if we can break between any two grapheme
    2520                 :      * clusters. This is set by word-wrap: break-word
    2521                 :      *
    2522                 :      * @param aBreakPriority in/out the priority of the break opportunity
    2523                 :      * saved in the line. If we are prioritizing break opportunities, we will
    2524                 :      * not set a break with a lower priority. @see gfxBreakPriority.
    2525                 :      * 
    2526                 :      * Note that negative advance widths are possible especially if negative
    2527                 :      * spacing is provided.
    2528                 :      */
    2529                 :     PRUint32 BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
    2530                 :                                  bool aLineBreakBefore, gfxFloat aWidth,
    2531                 :                                  PropertyProvider *aProvider,
    2532                 :                                  bool aSuppressInitialBreak,
    2533                 :                                  gfxFloat *aTrimWhitespace,
    2534                 :                                  Metrics *aMetrics,
    2535                 :                                  gfxFont::BoundingBoxType aBoundingBoxType,
    2536                 :                                  gfxContext *aRefContextForTightBoundingBox,
    2537                 :                                  bool *aUsedHyphenation,
    2538                 :                                  PRUint32 *aLastBreak,
    2539                 :                                  bool aCanWordWrap,
    2540                 :                                  gfxBreakPriority *aBreakPriority);
    2541                 : 
    2542                 :     /**
    2543                 :      * Update the reference context.
    2544                 :      * XXX this is a hack. New text frame does not call this. Use only
    2545                 :      * temporarily for old text frame.
    2546                 :      */
    2547                 :     void SetContext(gfxContext *aContext) {}
    2548                 : 
    2549                 :     // Utility getters
    2550                 : 
    2551               0 :     bool IsRightToLeft() const { return (mFlags & gfxTextRunFactory::TEXT_IS_RTL) != 0; }
    2552               0 :     gfxFloat GetDirection() const { return (mFlags & gfxTextRunFactory::TEXT_IS_RTL) ? -1.0 : 1.0; }
    2553                 :     void *GetUserData() const { return mUserData; }
    2554                 :     void SetUserData(void *aUserData) { mUserData = aUserData; }
    2555               0 :     PRUint32 GetFlags() const { return mFlags; }
    2556                 :     void SetFlagBits(PRUint32 aFlags) {
    2557                 :       NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
    2558                 :                    "Only user flags should be mutable");
    2559                 :       mFlags |= aFlags;
    2560                 :     }
    2561                 :     void ClearFlagBits(PRUint32 aFlags) {
    2562                 :       NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
    2563                 :                    "Only user flags should be mutable");
    2564                 :       mFlags &= ~aFlags;
    2565                 :     }
    2566                 :     const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
    2567               0 :     PRUint32 GetAppUnitsPerDevUnit() const { return mAppUnitsPerDevUnit; }
    2568                 :     gfxFontGroup *GetFontGroup() const { return mFontGroup; }
    2569                 : 
    2570                 : 
    2571                 :     // Call this, don't call "new gfxTextRun" directly. This does custom
    2572                 :     // allocation and initialization
    2573                 :     static gfxTextRun *Create(const gfxTextRunFactory::Parameters *aParams,
    2574                 :         const void *aText, PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags);
    2575                 : 
    2576                 :     // The text is divided into GlyphRuns as necessary
    2577               0 :     struct GlyphRun {
    2578                 :         nsRefPtr<gfxFont> mFont;   // never null
    2579                 :         PRUint32          mCharacterOffset; // into original UTF16 string
    2580                 :         PRUint8           mMatchType;
    2581                 :     };
    2582                 : 
    2583                 :     class THEBES_API GlyphRunIterator {
    2584                 :     public:
    2585               0 :         GlyphRunIterator(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aLength)
    2586               0 :           : mTextRun(aTextRun), mStartOffset(aStart), mEndOffset(aStart + aLength) {
    2587               0 :             mNextIndex = mTextRun->FindFirstGlyphRunContaining(aStart);
    2588               0 :         }
    2589                 :         bool NextRun();
    2590               0 :         GlyphRun *GetGlyphRun() { return mGlyphRun; }
    2591               0 :         PRUint32 GetStringStart() { return mStringStart; }
    2592               0 :         PRUint32 GetStringEnd() { return mStringEnd; }
    2593                 :     private:
    2594                 :         gfxTextRun *mTextRun;
    2595                 :         GlyphRun   *mGlyphRun;
    2596                 :         PRUint32    mStringStart;
    2597                 :         PRUint32    mStringEnd;
    2598                 :         PRUint32    mNextIndex;
    2599                 :         PRUint32    mStartOffset;
    2600                 :         PRUint32    mEndOffset;
    2601                 :     };
    2602                 : 
    2603                 :     class GlyphRunOffsetComparator {
    2604                 :     public:
    2605               0 :         bool Equals(const GlyphRun& a,
    2606                 :                       const GlyphRun& b) const
    2607                 :         {
    2608               0 :             return a.mCharacterOffset == b.mCharacterOffset;
    2609                 :         }
    2610                 : 
    2611               0 :         bool LessThan(const GlyphRun& a,
    2612                 :                         const GlyphRun& b) const
    2613                 :         {
    2614               0 :             return a.mCharacterOffset < b.mCharacterOffset;
    2615                 :         }
    2616                 :     };
    2617                 : 
    2618                 :     friend class GlyphRunIterator;
    2619                 :     friend class FontSelector;
    2620                 : 
    2621                 :     // API for setting up the textrun glyphs. Should only be called by
    2622                 :     // things that construct textruns.
    2623                 :     /**
    2624                 :      * We've found a run of text that should use a particular font. Call this
    2625                 :      * only during initialization when font substitution has been computed.
    2626                 :      * Call it before setting up the glyphs for the characters in this run;
    2627                 :      * SetMissingGlyph requires that the correct glyphrun be installed.
    2628                 :      *
    2629                 :      * If aForceNewRun, a new glyph run will be added, even if the
    2630                 :      * previously added run uses the same font.  If glyph runs are
    2631                 :      * added out of strictly increasing aStartCharIndex order (via
    2632                 :      * force), then SortGlyphRuns must be called after all glyph runs
    2633                 :      * are added before any further operations are performed with this
    2634                 :      * TextRun.
    2635                 :      */
    2636                 :     nsresult AddGlyphRun(gfxFont *aFont, PRUint8 aMatchType,
    2637                 :                          PRUint32 aStartCharIndex, bool aForceNewRun);
    2638                 :     void ResetGlyphRuns() { mGlyphRuns.Clear(); }
    2639                 :     void SortGlyphRuns();
    2640                 :     void SanitizeGlyphRuns();
    2641                 : 
    2642                 :     // Call the following glyph-setters during initialization or during reshaping
    2643                 :     // only. It is OK to overwrite existing data for a character.
    2644               0 :     void SetSimpleGlyph(PRUint32 aCharIndex, CompressedGlyph aGlyph) {
    2645               0 :         NS_ASSERTION(aGlyph.IsSimpleGlyph(), "Should be a simple glyph here");
    2646               0 :         mCharacterGlyphs[aCharIndex] = aGlyph;
    2647               0 :     }
    2648                 :     /**
    2649                 :      * Set the glyph data for a character. aGlyphs may be null if aGlyph is a
    2650                 :      * simple glyph or has no associated glyphs. If non-null the data is copied,
    2651                 :      * the caller retains ownership.
    2652                 :      */
    2653                 :     void SetGlyphs(PRUint32 aCharIndex, CompressedGlyph aGlyph,
    2654                 :                    const DetailedGlyph *aGlyphs);
    2655                 :     void SetMissingGlyph(PRUint32 aCharIndex, PRUint32 aUnicodeChar);
    2656                 :     void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, PRUint32 aCharIndex);
    2657                 : 
    2658                 :     // Set the glyph data for the given character index to the font's
    2659                 :     // space glyph, IF this can be done as a "simple" glyph record
    2660                 :     // (not requiring a DetailedGlyph entry). This avoids the need to call
    2661                 :     // the font shaper and go through the shaped-word cache for most spaces.
    2662                 :     //
    2663                 :     // The parameter aSpaceChar is the original character code for which
    2664                 :     // this space glyph is being used; if this is U+0020, we need to record
    2665                 :     // that it could be trimmed at a run edge, whereas other kinds of space
    2666                 :     // (currently just U+00A0) would not be trimmable/breakable.
    2667                 :     //
    2668                 :     // Returns true if it was able to set simple glyph data for the space;
    2669                 :     // if it returns false, the caller needs to fall back to some other
    2670                 :     // means to create the necessary (detailed) glyph data.
    2671                 :     bool SetSpaceGlyphIfSimple(gfxFont *aFont, gfxContext *aContext,
    2672                 :                                PRUint32 aCharIndex, PRUnichar aSpaceChar);
    2673                 : 
    2674                 :     // Record the positions of specific characters that layout may need to
    2675                 :     // detect in the textrun, even though it doesn't have an explicit copy
    2676                 :     // of the original text. These are recorded using flag bits in the
    2677                 :     // CompressedGlyph record; if necessary, we convert "simple" glyph records
    2678                 :     // to "complex" ones as the Tab and Newline flags are not present in
    2679                 :     // simple CompressedGlyph records.
    2680               0 :     void SetIsTab(PRUint32 aIndex) {
    2681               0 :         CompressedGlyph *g = &mCharacterGlyphs[aIndex];
    2682               0 :         if (g->IsSimpleGlyph()) {
    2683               0 :             DetailedGlyph *details = AllocateDetailedGlyphs(aIndex, 1);
    2684               0 :             details->mGlyphID = g->GetSimpleGlyph();
    2685               0 :             details->mAdvance = g->GetSimpleAdvance();
    2686               0 :             details->mXOffset = details->mYOffset = 0;
    2687               0 :             SetGlyphs(aIndex, CompressedGlyph().SetComplex(true, true, 1), details);
    2688                 :         }
    2689               0 :         g->SetIsTab();
    2690               0 :     }
    2691               0 :     void SetIsNewline(PRUint32 aIndex) {
    2692               0 :         CompressedGlyph *g = &mCharacterGlyphs[aIndex];
    2693               0 :         if (g->IsSimpleGlyph()) {
    2694               0 :             DetailedGlyph *details = AllocateDetailedGlyphs(aIndex, 1);
    2695               0 :             details->mGlyphID = g->GetSimpleGlyph();
    2696               0 :             details->mAdvance = g->GetSimpleAdvance();
    2697               0 :             details->mXOffset = details->mYOffset = 0;
    2698               0 :             SetGlyphs(aIndex, CompressedGlyph().SetComplex(true, true, 1), details);
    2699                 :         }
    2700               0 :         g->SetIsNewline();
    2701               0 :     }
    2702               0 :     void SetIsLowSurrogate(PRUint32 aIndex) {
    2703               0 :         SetGlyphs(aIndex, CompressedGlyph().SetComplex(false, false, 0), nsnull);
    2704               0 :         mCharacterGlyphs[aIndex].SetIsLowSurrogate();
    2705               0 :     }
    2706                 : 
    2707                 :     /**
    2708                 :      * Prefetch all the glyph extents needed to ensure that Measure calls
    2709                 :      * on this textrun not requesting tight boundingBoxes will succeed. Note
    2710                 :      * that some glyph extents might not be fetched due to OOM or other
    2711                 :      * errors.
    2712                 :      */
    2713                 :     void FetchGlyphExtents(gfxContext *aRefContext);
    2714                 : 
    2715                 :     // API for access to the raw glyph data, needed by gfxFont::Draw
    2716                 :     // and gfxFont::GetBoundingBox
    2717               0 :     CompressedGlyph *GetCharacterGlyphs() { return mCharacterGlyphs; }
    2718                 : 
    2719                 :     // NOTE that this must not be called for a character offset that does
    2720                 :     // not have any DetailedGlyph records; callers must have verified that
    2721                 :     // mCharacterGlyphs[aCharIndex].GetGlyphCount() is greater than zero.
    2722               0 :     DetailedGlyph *GetDetailedGlyphs(PRUint32 aCharIndex) {
    2723               0 :         NS_ASSERTION(mDetailedGlyphs != nsnull &&
    2724                 :                      !mCharacterGlyphs[aCharIndex].IsSimpleGlyph() &&
    2725                 :                      mCharacterGlyphs[aCharIndex].GetGlyphCount() > 0,
    2726                 :                      "invalid use of GetDetailedGlyphs; check the caller!");
    2727               0 :         return mDetailedGlyphs->Get(aCharIndex);
    2728                 :     }
    2729                 : 
    2730               0 :     bool HasDetailedGlyphs() { return mDetailedGlyphs != nsnull; }
    2731                 :     PRUint32 CountMissingGlyphs();
    2732               0 :     const GlyphRun *GetGlyphRuns(PRUint32 *aNumGlyphRuns) {
    2733               0 :         *aNumGlyphRuns = mGlyphRuns.Length();
    2734               0 :         return mGlyphRuns.Elements();
    2735                 :     }
    2736                 :     // Returns the index of the GlyphRun containing the given offset.
    2737                 :     // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
    2738                 :     PRUint32 FindFirstGlyphRunContaining(PRUint32 aOffset);
    2739                 : 
    2740                 :     // Copy glyph data from a ShapedWord into this textrun.
    2741                 :     void CopyGlyphDataFrom(const gfxShapedWord *aSource, PRUint32 aStart);
    2742                 : 
    2743                 :     // Copy glyph data for a range of characters from aSource to this
    2744                 :     // textrun.
    2745                 :     void CopyGlyphDataFrom(gfxTextRun *aSource, PRUint32 aStart,
    2746                 :                            PRUint32 aLength, PRUint32 aDest);
    2747                 : 
    2748                 :     nsExpirationState *GetExpirationState() { return &mExpirationState; }
    2749                 : 
    2750                 :     struct LigatureData {
    2751                 :         // textrun offsets of the start and end of the containing ligature
    2752                 :         PRUint32 mLigatureStart;
    2753                 :         PRUint32 mLigatureEnd;
    2754                 :         // appunits advance to the start of the ligature part within the ligature;
    2755                 :         // never includes any spacing
    2756                 :         gfxFloat mPartAdvance;
    2757                 :         // appunits width of the ligature part; includes before-spacing
    2758                 :         // when the part is at the start of the ligature, and after-spacing
    2759                 :         // when the part is as the end of the ligature
    2760                 :         gfxFloat mPartWidth;
    2761                 :         
    2762                 :         bool mClipBeforePart;
    2763                 :         bool mClipAfterPart;
    2764                 :     };
    2765                 :     
    2766                 :     // return storage used by this run, for memory reporter;
    2767                 :     // nsTransformedTextRun needs to override this as it holds additional data
    2768                 :     virtual NS_MUST_OVERRIDE size_t
    2769                 :         SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf);
    2770                 :     virtual NS_MUST_OVERRIDE size_t
    2771                 :         SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
    2772                 : 
    2773                 :     // Get the size, if it hasn't already been gotten, marking as it goes.
    2774                 :     size_t MaybeSizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)  {
    2775                 :         if (mFlags & gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED) {
    2776                 :             return 0;
    2777                 :         }
    2778                 :         mFlags |= gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
    2779                 :         return SizeOfIncludingThis(aMallocSizeOf);
    2780                 :     }
    2781                 :     void ResetSizeOfAccountingFlags() {
    2782                 :         mFlags &= ~gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
    2783                 :     }
    2784                 : 
    2785                 : #ifdef DEBUG
    2786                 :     void Dump(FILE* aOutput);
    2787                 : #endif
    2788                 : 
    2789                 : protected:
    2790                 :     /**
    2791                 :      * Create a textrun, and set its mCharacterGlyphs to point immediately
    2792                 :      * after the base object; this is ONLY used in conjunction with placement
    2793                 :      * new, after allocating a block large enough for the glyph records to
    2794                 :      * follow the base textrun object.
    2795                 :      */
    2796                 :     gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void *aText,
    2797                 :                PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags);
    2798                 : 
    2799                 :     /**
    2800                 :      * Helper for the Create() factory method to allocate the required
    2801                 :      * glyph storage for a textrun object with the basic size aSize,
    2802                 :      * plus room for aLength glyph records.
    2803                 :      */
    2804                 :     static void* AllocateStorageForTextRun(size_t aSize, PRUint32 aLength);
    2805                 : 
    2806                 :     // All our glyph data is in logical order, not visual.
    2807                 :     // Space for mCharacterGlyphs is allocated fused with the textrun object,
    2808                 :     // and then the constructor sets the pointer to the beginning of this
    2809                 :     // storage area. Thus, this pointer must NOT be freed!
    2810                 :     CompressedGlyph  *mCharacterGlyphs;
    2811                 : 
    2812                 : private:
    2813                 :     // **** general helpers **** 
    2814                 : 
    2815                 :     // Allocate aCount DetailedGlyphs for the given index
    2816                 :     DetailedGlyph *AllocateDetailedGlyphs(PRUint32 aCharIndex, PRUint32 aCount);
    2817                 : 
    2818                 :     // Get the total advance for a range of glyphs.
    2819                 :     PRInt32 GetAdvanceForGlyphs(PRUint32 aStart, PRUint32 aEnd);
    2820                 : 
    2821                 :     // Spacing for characters outside the range aSpacingStart/aSpacingEnd
    2822                 :     // is assumed to be zero; such characters are not passed to aProvider.
    2823                 :     // This is useful to protect aProvider from being passed character indices
    2824                 :     // it is not currently able to handle.
    2825                 :     bool GetAdjustedSpacingArray(PRUint32 aStart, PRUint32 aEnd,
    2826                 :                                    PropertyProvider *aProvider,
    2827                 :                                    PRUint32 aSpacingStart, PRUint32 aSpacingEnd,
    2828                 :                                    nsTArray<PropertyProvider::Spacing> *aSpacing);
    2829                 : 
    2830                 :     //  **** ligature helpers ****
    2831                 :     // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
    2832                 :     // to handle requests that begin or end inside a ligature)
    2833                 : 
    2834                 :     // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
    2835                 :     LigatureData ComputeLigatureData(PRUint32 aPartStart, PRUint32 aPartEnd,
    2836                 :                                      PropertyProvider *aProvider);
    2837                 :     gfxFloat ComputePartialLigatureWidth(PRUint32 aPartStart, PRUint32 aPartEnd,
    2838                 :                                          PropertyProvider *aProvider);
    2839                 :     void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
    2840                 :                              PRUint32 aStart, PRUint32 aEnd, gfxPoint *aPt,
    2841                 :                              PropertyProvider *aProvider);
    2842                 :     // Advance aStart to the start of the nearest ligature; back up aEnd
    2843                 :     // to the nearest ligature end; may result in *aStart == *aEnd
    2844                 :     void ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd);
    2845                 :     // result in appunits
    2846                 :     gfxFloat GetPartialLigatureWidth(PRUint32 aStart, PRUint32 aEnd, PropertyProvider *aProvider);
    2847                 :     void AccumulatePartialLigatureMetrics(gfxFont *aFont,
    2848                 :                                           PRUint32 aStart, PRUint32 aEnd,
    2849                 :                                           gfxFont::BoundingBoxType aBoundingBoxType,
    2850                 :                                           gfxContext *aRefContext,
    2851                 :                                           PropertyProvider *aProvider,
    2852                 :                                           Metrics *aMetrics);
    2853                 : 
    2854                 :     // **** measurement helper ****
    2855                 :     void AccumulateMetricsForRun(gfxFont *aFont, PRUint32 aStart, PRUint32 aEnd,
    2856                 :                                  gfxFont::BoundingBoxType aBoundingBoxType,
    2857                 :                                  gfxContext *aRefContext,
    2858                 :                                  PropertyProvider *aProvider,
    2859                 :                                  PRUint32 aSpacingStart, PRUint32 aSpacingEnd,
    2860                 :                                  Metrics *aMetrics);
    2861                 : 
    2862                 :     // **** drawing helper ****
    2863                 :     void DrawGlyphs(gfxFont *aFont, gfxContext *aContext,
    2864                 :                     gfxFont::DrawMode aDrawMode, gfxPoint *aPt,
    2865                 :                     gfxPattern *aStrokePattern, PRUint32 aStart, PRUint32 aEnd,
    2866                 :                     PropertyProvider *aProvider,
    2867                 :                     PRUint32 aSpacingStart, PRUint32 aSpacingEnd);
    2868                 : 
    2869                 :     nsAutoPtr<DetailedGlyphStore>   mDetailedGlyphs;
    2870                 : 
    2871                 :     // XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*,
    2872                 :     // for smaller size especially in the super-common one-glyphrun case
    2873                 :     nsAutoTArray<GlyphRun,1>        mGlyphRuns;
    2874                 : 
    2875                 :     void             *mUserData;
    2876                 :     gfxFontGroup     *mFontGroup; // addrefed
    2877                 :     gfxSkipChars      mSkipChars;
    2878                 :     nsExpirationState mExpirationState;
    2879                 :     PRUint32          mAppUnitsPerDevUnit;
    2880                 :     PRUint32          mFlags;
    2881                 :     PRUint32          mCharacterCount;
    2882                 : 
    2883                 :     bool              mSkipDrawing; // true if the font group we used had a user font
    2884                 :                                     // download that's in progress, so we should hide text
    2885                 :                                     // until the download completes (or timeout fires)
    2886                 : };
    2887                 : 
    2888                 : class THEBES_API gfxFontGroup : public gfxTextRunFactory {
    2889                 : public:
    2890                 :     static void Shutdown(); // platform must call this to release the languageAtomService
    2891                 : 
    2892                 :     gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet = nsnull);
    2893                 : 
    2894                 :     virtual ~gfxFontGroup();
    2895                 : 
    2896               0 :     virtual gfxFont *GetFontAt(PRInt32 i) {
    2897                 :         // If it turns out to be hard for all clients that cache font
    2898                 :         // groups to call UpdateFontList at appropriate times, we could
    2899                 :         // instead consider just calling UpdateFontList from someplace
    2900                 :         // more central (such as here).
    2901               0 :         NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
    2902                 :                      "Whoever was caching this font group should have "
    2903                 :                      "called UpdateFontList on it");
    2904               0 :         NS_ASSERTION(mFonts.Length() > PRUint32(i), 
    2905                 :                      "Requesting a font index that doesn't exist");
    2906                 : 
    2907               0 :         return static_cast<gfxFont*>(mFonts[i]);
    2908                 :     }
    2909               0 :     virtual PRUint32 FontListLength() const {
    2910               0 :         return mFonts.Length();
    2911                 :     }
    2912                 : 
    2913                 :     bool Equals(const gfxFontGroup& other) const {
    2914                 :         return mFamilies.Equals(other.mFamilies) &&
    2915                 :             mStyle.Equals(other.mStyle);
    2916                 :     }
    2917                 : 
    2918               0 :     const gfxFontStyle *GetStyle() const { return &mStyle; }
    2919                 : 
    2920                 :     virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
    2921                 : 
    2922                 :     /**
    2923                 :      * The listed characters should be treated as invisible and zero-width
    2924                 :      * when creating textruns.
    2925                 :      */
    2926                 :     static bool IsInvalidChar(PRUint8 ch);
    2927                 :     static bool IsInvalidChar(PRUnichar ch);
    2928                 : 
    2929                 :     /**
    2930                 :      * Make a textrun for a given string.
    2931                 :      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
    2932                 :      * textrun will copy it.
    2933                 :      * This calls FetchGlyphExtents on the textrun.
    2934                 :      */
    2935                 :     virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
    2936                 :                                     const Parameters *aParams, PRUint32 aFlags);
    2937                 :     /**
    2938                 :      * Make a textrun for a given string.
    2939                 :      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
    2940                 :      * textrun will copy it.
    2941                 :      * This calls FetchGlyphExtents on the textrun.
    2942                 :      */
    2943                 :     virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
    2944                 :                                     const Parameters *aParams, PRUint32 aFlags);
    2945                 : 
    2946                 :     /**
    2947                 :      * Textrun creation helper for clients that don't want to pass
    2948                 :      * a full Parameters record.
    2949                 :      */
    2950                 :     template<typename T>
    2951                 :     gfxTextRun *MakeTextRun(const T *aString, PRUint32 aLength,
    2952                 :                             gfxContext *aRefContext,
    2953                 :                             PRUint32 aAppUnitsPerDevUnit,
    2954                 :                             PRUint32 aFlags)
    2955                 :     {
    2956                 :         gfxTextRunFactory::Parameters params = {
    2957                 :             aRefContext, nsnull, nsnull, nsnull, 0, aAppUnitsPerDevUnit
    2958                 :         };
    2959                 :         return MakeTextRun(aString, aLength, &params, aFlags);
    2960                 :     }
    2961                 : 
    2962                 :     /* helper function for splitting font families on commas and
    2963                 :      * calling a function for each family to fill the mFonts array
    2964                 :      */
    2965                 :     typedef bool (*FontCreationCallback) (const nsAString& aName,
    2966                 :                                             const nsACString& aGenericName,
    2967                 :                                             bool aUseFontSet,
    2968                 :                                             void *closure);
    2969                 :     bool ForEachFont(const nsAString& aFamilies,
    2970                 :                        nsIAtom *aLanguage,
    2971                 :                        FontCreationCallback fc,
    2972                 :                        void *closure);
    2973                 :     bool ForEachFont(FontCreationCallback fc, void *closure);
    2974                 : 
    2975                 :     /**
    2976                 :      * Check whether a given font (specified by its gfxFontEntry)
    2977                 :      * is already in the fontgroup's list of actual fonts
    2978                 :      */
    2979                 :     bool HasFont(const gfxFontEntry *aFontEntry);
    2980                 : 
    2981                 :     const nsString& GetFamilies() { return mFamilies; }
    2982                 : 
    2983                 :     // This returns the preferred underline for this font group.
    2984                 :     // Some CJK fonts have wrong underline offset in its metrics.
    2985                 :     // If this group has such "bad" font, each platform's gfxFontGroup initialized mUnderlineOffset.
    2986                 :     // The value should be lower value of first font's metrics and the bad font's metrics.
    2987                 :     // Otherwise, this returns from first font's metrics.
    2988                 :     enum { UNDERLINE_OFFSET_NOT_SET = PR_INT16_MAX };
    2989               0 :     virtual gfxFloat GetUnderlineOffset() {
    2990               0 :         if (mUnderlineOffset == UNDERLINE_OFFSET_NOT_SET)
    2991               0 :             mUnderlineOffset = GetFontAt(0)->GetMetrics().underlineOffset;
    2992               0 :         return mUnderlineOffset;
    2993                 :     }
    2994                 : 
    2995                 :     virtual already_AddRefed<gfxFont>
    2996                 :         FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRInt32 aRunScript,
    2997                 :                         gfxFont *aPrevMatchedFont,
    2998                 :                         PRUint8 *aMatchType);
    2999                 : 
    3000                 :     // search through pref fonts for a character, return nsnull if no matching pref font
    3001                 :     virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
    3002                 : 
    3003                 :     virtual already_AddRefed<gfxFont>
    3004                 :         WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript);
    3005                 : 
    3006                 :     template<typename T>
    3007                 :     void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
    3008                 :                        const T *aString, PRUint32 aLength,
    3009                 :                        PRInt32 aRunScript);
    3010                 : 
    3011                 :     gfxUserFontSet* GetUserFontSet();
    3012                 : 
    3013                 :     // With downloadable fonts, the composition of the font group can change as fonts are downloaded
    3014                 :     // for each change in state of the user font set, the generation value is bumped to avoid picking up
    3015                 :     // previously created text runs in the text run word cache.  For font groups based on stylesheets
    3016                 :     // with no @font-face rule, this always returns 0.
    3017                 :     PRUint64 GetGeneration();
    3018                 : 
    3019                 :     // If there is a user font set, check to see whether the font list or any
    3020                 :     // caches need updating.
    3021                 :     virtual void UpdateFontList();
    3022                 : 
    3023               0 :     bool ShouldSkipDrawing() const {
    3024               0 :         return mSkipDrawing;
    3025                 :     }
    3026                 : 
    3027                 : protected:
    3028                 :     nsString mFamilies;
    3029                 :     gfxFontStyle mStyle;
    3030                 :     nsTArray< nsRefPtr<gfxFont> > mFonts;
    3031                 :     gfxFloat mUnderlineOffset;
    3032                 : 
    3033                 :     gfxUserFontSet* mUserFontSet;
    3034                 :     PRUint64 mCurrGeneration;  // track the current user font set generation, rebuild font list if needed
    3035                 : 
    3036                 :     // cache the most recent pref font to avoid general pref font lookup
    3037                 :     nsRefPtr<gfxFontFamily> mLastPrefFamily;
    3038                 :     nsRefPtr<gfxFont>       mLastPrefFont;
    3039                 :     eFontPrefLang           mLastPrefLang;       // lang group for last pref font
    3040                 :     eFontPrefLang           mPageLang;
    3041                 :     bool                    mLastPrefFirstFont;  // is this the first font in the list of pref fonts for this lang group?
    3042                 : 
    3043                 :     bool                    mSkipDrawing; // hide text while waiting for a font
    3044                 :                                           // download to complete (or fallback
    3045                 :                                           // timer to fire)
    3046                 : 
    3047                 :     /**
    3048                 :      * Textrun creation short-cuts for special cases where we don't need to
    3049                 :      * call a font shaper to generate glyphs.
    3050                 :      */
    3051                 :     gfxTextRun *MakeEmptyTextRun(const Parameters *aParams, PRUint32 aFlags);
    3052                 :     gfxTextRun *MakeSpaceTextRun(const Parameters *aParams, PRUint32 aFlags);
    3053                 :     gfxTextRun *MakeBlankTextRun(const void* aText, PRUint32 aLength,
    3054                 :                                  const Parameters *aParams, PRUint32 aFlags);
    3055                 : 
    3056                 :     // Used for construction/destruction.  Not intended to change the font set
    3057                 :     // as invalidation of font lists and caches is not considered.
    3058                 :     void SetUserFontSet(gfxUserFontSet *aUserFontSet);
    3059                 : 
    3060                 :     // Initialize the list of fonts
    3061                 :     void BuildFontList();
    3062                 : 
    3063                 :     // Init this font group's font metrics. If there no bad fonts, you don't need to call this.
    3064                 :     // But if there are one or more bad fonts which have bad underline offset,
    3065                 :     // you should call this with the *first* bad font.
    3066                 :     void InitMetricsForBadFont(gfxFont* aBadFont);
    3067                 : 
    3068                 :     // Set up the textrun glyphs for an entire text run:
    3069                 :     // find script runs, and then call InitScriptRun for each
    3070                 :     template<typename T>
    3071               0 :     void InitTextRun(gfxContext *aContext,
    3072                 :                      gfxTextRun *aTextRun,
    3073                 :                      const T *aString,
    3074                 :                      PRUint32 aLength);
    3075                 : 
    3076                 :     // InitTextRun helper to handle a single script run, by finding font ranges
    3077                 :     // and calling each font's InitTextRun() as appropriate
    3078                 :     template<typename T>
    3079               0 :     void InitScriptRun(gfxContext *aContext,
    3080                 :                        gfxTextRun *aTextRun,
    3081                 :                        const T *aString,
    3082                 :                        PRUint32 aScriptRunStart,
    3083                 :                        PRUint32 aScriptRunEnd,
    3084                 :                        PRInt32 aRunScript);
    3085                 : 
    3086                 :     /* If aResolveGeneric is true, then CSS/Gecko generic family names are
    3087                 :      * replaced with preferred fonts.
    3088                 :      *
    3089                 :      * If aResolveFontName is true then fc() is called only for existing fonts
    3090                 :      * and with actual font names.  If false then fc() is called with each
    3091                 :      * family name in aFamilies (after resolving CSS/Gecko generic family names
    3092                 :      * if aResolveGeneric).
    3093                 :      * If aUseFontSet is true, the fontgroup's user font set is checked;
    3094                 :      * if false then it is skipped.
    3095                 :      */
    3096                 :     bool ForEachFontInternal(const nsAString& aFamilies,
    3097                 :                                nsIAtom *aLanguage,
    3098                 :                                bool aResolveGeneric,
    3099                 :                                bool aResolveFontName,
    3100                 :                                bool aUseFontSet,
    3101                 :                                FontCreationCallback fc,
    3102                 :                                void *closure);
    3103                 : 
    3104                 :     static bool FontResolverProc(const nsAString& aName, void *aClosure);
    3105                 : 
    3106                 :     static bool FindPlatformFont(const nsAString& aName,
    3107                 :                                    const nsACString& aGenericName,
    3108                 :                                    bool aUseFontSet,
    3109                 :                                    void *closure);
    3110                 : 
    3111                 :     static NS_HIDDEN_(nsILanguageAtomService*) gLangService;
    3112                 : };
    3113                 : #endif

Generated by: LCOV version 1.7