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

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