gfx/thebes/gfxFont.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef GFX_FONT_H
     7 #define GFX_FONT_H
     9 #include "gfxTypes.h"
    10 #include "nsString.h"
    11 #include "gfxPoint.h"
    12 #include "gfxFontUtils.h"
    13 #include "nsTArray.h"
    14 #include "nsTHashtable.h"
    15 #include "nsHashKeys.h"
    16 #include "gfxSkipChars.h"
    17 #include "gfxRect.h"
    18 #include "nsExpirationTracker.h"
    19 #include "gfxPlatform.h"
    20 #include "nsIAtom.h"
    21 #include "mozilla/HashFunctions.h"
    22 #include "nsIMemoryReporter.h"
    23 #include "nsIObserver.h"
    24 #include "gfxFontFeatures.h"
    25 #include "mozilla/MemoryReporting.h"
    26 #include "mozilla/Attributes.h"
    27 #include <algorithm>
    28 #include "DrawMode.h"
    29 #include "nsUnicodeScriptCodes.h"
    30 #include "nsDataHashtable.h"
    31 #include "harfbuzz/hb.h"
    32 #include "mozilla/gfx/2D.h"
    34 typedef struct _cairo_scaled_font cairo_scaled_font_t;
    35 typedef struct gr_face            gr_face;
    37 #ifdef DEBUG
    38 #include <stdio.h>
    39 #endif
    41 class gfxContext;
    42 class gfxTextRun;
    43 class gfxFont;
    44 class gfxFontFamily;
    45 class gfxFontGroup;
    46 class gfxGraphiteShaper;
    47 class gfxHarfBuzzShaper;
    48 class gfxUserFontSet;
    49 class gfxUserFontData;
    50 class gfxShapedText;
    51 class gfxShapedWord;
    52 class gfxSVGGlyphs;
    53 class gfxMathTable;
    54 class gfxTextContextPaint;
    55 class FontInfoData;
    57 class nsILanguageAtomService;
    59 #define FONT_MAX_SIZE                  2000.0
    61 #define NO_FONT_LANGUAGE_OVERRIDE      0
    63 struct FontListSizes;
    64 struct gfxTextRunDrawCallbacks;
    66 namespace mozilla {
    67 namespace gfx {
    68 class GlyphRenderingOptions;
    69 }
    70 }
    72 struct gfxFontStyle {
    73     gfxFontStyle();
    74     gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
    75                  gfxFloat aSize, nsIAtom *aLanguage,
    76                  float aSizeAdjust, bool aSystemFont,
    77                  bool aPrinterFont,
    78                  const nsString& aLanguageOverride);
    79     gfxFontStyle(const gfxFontStyle& aStyle);
    81     // the language (may be an internal langGroup code rather than an actual
    82     // language code) specified in the document or element's lang property,
    83     // or inferred from the charset
    84     nsRefPtr<nsIAtom> language;
    86     // Features are composed of (1) features from style rules (2) features
    87     // from feature setttings rules and (3) family-specific features.  (1) and
    88     // (3) are guaranteed to be mutually exclusive
    90     // custom opentype feature settings
    91     nsTArray<gfxFontFeature> featureSettings;
    93     // Some font-variant property values require font-specific settings
    94     // defined via @font-feature-values rules.  These are resolved after
    95     // font matching occurs.
    97     // -- list of value tags for specific alternate features
    98     nsTArray<gfxAlternateValue> alternateValues;
   100     // -- object used to look these up once the font is matched
   101     nsRefPtr<gfxFontFeatureValueSet> featureValueLookup;
   103     // The logical size of the font, in pixels
   104     gfxFloat size;
   106     // The aspect-value (ie., the ratio actualsize:actualxheight) that any
   107     // actual physical font created from this font structure must have when
   108     // rendering or measuring a string. A value of 0 means no adjustment
   109     // needs to be done.
   110     float sizeAdjust;
   112     // Language system tag, to override document language;
   113     // an OpenType "language system" tag represented as a 32-bit integer
   114     // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
   115     // Normally 0, so font rendering will use the document or element language
   116     // (see above) to control any language-specific rendering, but the author
   117     // can override this for cases where the options implemented in the font
   118     // do not directly match the actual language. (E.g. lang may be Macedonian,
   119     // but the font in use does not explicitly support this; the author can
   120     // use font-language-override to request the Serbian option in the font
   121     // in order to get correct glyph shapes.)
   122     uint32_t languageOverride;
   124     // The weight of the font: 100, 200, ... 900.
   125     uint16_t weight;
   127     // The stretch of the font (the sum of various NS_FONT_STRETCH_*
   128     // constants; see gfxFontConstants.h).
   129     int8_t stretch;
   131     // Say that this font is a system font and therefore does not
   132     // require certain fixup that we do for fonts from untrusted
   133     // sources.
   134     bool systemFont : 1;
   136     // Say that this font is used for print or print preview.
   137     bool printerFont : 1;
   139     // Used to imitate -webkit-font-smoothing: antialiased
   140     bool useGrayscaleAntialiasing : 1;
   142     // The style of font (normal, italic, oblique)
   143     uint8_t style : 2;
   145     // Return the final adjusted font size for the given aspect ratio.
   146     // Not meant to be called when sizeAdjust = 0.
   147     gfxFloat GetAdjustedSize(gfxFloat aspect) const {
   148         NS_ASSERTION(sizeAdjust != 0.0, "Not meant to be called when sizeAdjust = 0");
   149         gfxFloat adjustedSize = std::max(NS_round(size*(sizeAdjust/aspect)), 1.0);
   150         return std::min(adjustedSize, FONT_MAX_SIZE);
   151     }
   153     PLDHashNumber Hash() const {
   154         return ((style + (systemFont << 7) +
   155             (weight << 8)) + uint32_t(size*1000) + uint32_t(sizeAdjust*1000)) ^
   156             nsISupportsHashKey::HashKey(language);
   157     }
   159     int8_t ComputeWeight() const;
   161     bool Equals(const gfxFontStyle& other) const {
   162         return
   163             (*reinterpret_cast<const uint64_t*>(&size) ==
   164              *reinterpret_cast<const uint64_t*>(&other.size)) &&
   165             (style == other.style) &&
   166             (systemFont == other.systemFont) &&
   167             (printerFont == other.printerFont) &&
   168             (useGrayscaleAntialiasing == other.useGrayscaleAntialiasing) &&
   169             (weight == other.weight) &&
   170             (stretch == other.stretch) &&
   171             (language == other.language) &&
   172             (*reinterpret_cast<const uint32_t*>(&sizeAdjust) ==
   173              *reinterpret_cast<const uint32_t*>(&other.sizeAdjust)) &&
   174             (featureSettings == other.featureSettings) &&
   175             (languageOverride == other.languageOverride) &&
   176             (alternateValues == other.alternateValues) &&
   177             (featureValueLookup == other.featureValueLookup);
   178     }
   180     static void ParseFontFeatureSettings(const nsString& aFeatureString,
   181                                          nsTArray<gfxFontFeature>& aFeatures);
   183     static uint32_t ParseFontLanguageOverride(const nsString& aLangTag);
   184 };
   186 class gfxCharacterMap : public gfxSparseBitSet {
   187 public:
   188     nsrefcnt AddRef() {
   189         NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
   190         ++mRefCnt;
   191         NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
   192         return mRefCnt;
   193     }
   195     nsrefcnt Release() {
   196         NS_PRECONDITION(0 != mRefCnt, "dup release");
   197         --mRefCnt;
   198         NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
   199         if (mRefCnt == 0) {
   200             NotifyReleased();
   201             // |this| has been deleted.
   202             return 0;
   203         }
   204         return mRefCnt;
   205     }
   207     gfxCharacterMap() :
   208         mHash(0), mBuildOnTheFly(false), mShared(false)
   209     { }
   211     void CalcHash() { mHash = GetChecksum(); }
   213     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
   214         return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
   215     }
   217     // hash of the cmap bitvector
   218     uint32_t mHash;
   220     // if cmap is built on the fly it's never shared
   221     bool mBuildOnTheFly;
   223     // cmap is shared globally
   224     bool mShared;
   226 protected:
   227     void NotifyReleased();
   229     nsAutoRefCnt mRefCnt;
   231 private:
   232     gfxCharacterMap(const gfxCharacterMap&);
   233     gfxCharacterMap& operator=(const gfxCharacterMap&);
   234 };
   236 class gfxFontEntry {
   237 public:
   238     NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
   240     gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false);
   242     // unique name for the face, *not* the family; not necessarily the
   243     // "real" or user-friendly name, may be an internal identifier
   244     const nsString& Name() const { return mName; }
   246     // family name
   247     const nsString& FamilyName() const { return mFamilyName; }
   249     // The following two methods may be relatively expensive, as they
   250     // will (usually, except on Linux) load and parse the 'name' table;
   251     // they are intended only for the font-inspection API, not for
   252     // perf-critical layout/drawing work.
   254     // The "real" name of the face, if available from the font resource;
   255     // returns Name() if nothing better is available.
   256     virtual nsString RealFaceName();
   258     uint16_t Weight() const { return mWeight; }
   259     int16_t Stretch() const { return mStretch; }
   261     bool IsUserFont() const { return mIsUserFont; }
   262     bool IsLocalUserFont() const { return mIsLocalUserFont; }
   263     bool IsFixedPitch() const { return mFixedPitch; }
   264     bool IsItalic() const { return mItalic; }
   265     bool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
   266     bool IgnoreGDEF() const { return mIgnoreGDEF; }
   267     bool IgnoreGSUB() const { return mIgnoreGSUB; }
   269     virtual bool IsSymbolFont();
   271     virtual bool HasFontTable(uint32_t aTableTag);
   273     inline bool HasGraphiteTables() {
   274         if (!mCheckedForGraphiteTables) {
   275             CheckForGraphiteTables();
   276             mCheckedForGraphiteTables = true;
   277         }
   278         return mHasGraphiteTables;
   279     }
   281     inline bool HasCmapTable() {
   282         if (!mCharacterMap) {
   283             ReadCMAP();
   284             NS_ASSERTION(mCharacterMap, "failed to initialize character map");
   285         }
   286         return mHasCmapTable;
   287     }
   289     inline bool HasCharacter(uint32_t ch) {
   290         if (mCharacterMap && mCharacterMap->test(ch)) {
   291             return true;
   292         }
   293         return TestCharacterMap(ch);
   294     }
   296     virtual bool SkipDuringSystemFallback() { return false; }
   297     virtual bool TestCharacterMap(uint32_t aCh);
   298     nsresult InitializeUVSMap();
   299     uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS);
   301     // All concrete gfxFontEntry subclasses (except gfxProxyFontEntry) need
   302     // to override this, otherwise the font will never be used as it will
   303     // be considered to support no characters.
   304     // ReadCMAP() must *always* set the mCharacterMap pointer to a valid
   305     // gfxCharacterMap, even if empty, as other code assumes this pointer
   306     // can be safely dereferenced.
   307     virtual nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
   309     bool TryGetSVGData(gfxFont* aFont);
   310     bool HasSVGGlyph(uint32_t aGlyphId);
   311     bool GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
   312                             gfxRect *aResult);
   313     bool RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId, int aDrawMode,
   314                         gfxTextContextPaint *aContextPaint);
   315     // Call this when glyph geometry or rendering has changed
   316     // (e.g. animated SVG glyphs)
   317     void NotifyGlyphsChanged();
   319     enum MathConstant {
   320         // The order of the constants must match the order of the fields
   321         // defined in the MATH table.
   322         ScriptPercentScaleDown,
   323         ScriptScriptPercentScaleDown,
   324         DelimitedSubFormulaMinHeight,
   325         DisplayOperatorMinHeight,
   326         MathLeading,
   327         AxisHeight,
   328         AccentBaseHeight,
   329         FlattenedAccentBaseHeight,
   330         SubscriptShiftDown,
   331         SubscriptTopMax,
   332         SubscriptBaselineDropMin,
   333         SuperscriptShiftUp,
   334         SuperscriptShiftUpCramped,
   335         SuperscriptBottomMin,
   336         SuperscriptBaselineDropMax,
   337         SubSuperscriptGapMin,
   338         SuperscriptBottomMaxWithSubscript,
   339         SpaceAfterScript,
   340         UpperLimitGapMin,
   341         UpperLimitBaselineRiseMin,
   342         LowerLimitGapMin,
   343         LowerLimitBaselineDropMin,
   344         StackTopShiftUp,
   345         StackTopDisplayStyleShiftUp,
   346         StackBottomShiftDown,
   347         StackBottomDisplayStyleShiftDown,
   348         StackGapMin,
   349         StackDisplayStyleGapMin,
   350         StretchStackTopShiftUp,
   351         StretchStackBottomShiftDown,
   352         StretchStackGapAboveMin,
   353         StretchStackGapBelowMin,
   354         FractionNumeratorShiftUp,
   355         FractionNumeratorDisplayStyleShiftUp,
   356         FractionDenominatorShiftDown,
   357         FractionDenominatorDisplayStyleShiftDown,
   358         FractionNumeratorGapMin,
   359         FractionNumDisplayStyleGapMin,
   360         FractionRuleThickness,
   361         FractionDenominatorGapMin,
   362         FractionDenomDisplayStyleGapMin,
   363         SkewedFractionHorizontalGap,
   364         SkewedFractionVerticalGap,
   365         OverbarVerticalGap,
   366         OverbarRuleThickness,
   367         OverbarExtraAscender,
   368         UnderbarVerticalGap,
   369         UnderbarRuleThickness,
   370         UnderbarExtraDescender,
   371         RadicalVerticalGap,
   372         RadicalDisplayStyleVerticalGap,
   373         RadicalRuleThickness,
   374         RadicalExtraAscender,
   375         RadicalKernBeforeDegree,
   376         RadicalKernAfterDegree,
   377         RadicalDegreeBottomRaisePercent
   378     };
   380     // Call TryGetMathTable to try to load the Open Type MATH table. The other
   381     // functions forward the call to the gfxMathTable class. The GetMath...()
   382     // functions MUST NOT be called unless TryGetMathTable() has returned true.
   383     bool     TryGetMathTable(gfxFont* aFont);
   384     gfxFloat GetMathConstant(MathConstant aConstant);
   385     bool     GetMathItalicsCorrection(uint32_t aGlyphID,
   386                                       gfxFloat* aItalicCorrection);
   387     uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
   388                                  uint16_t aSize);
   389     bool     GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
   390                                   uint32_t aGlyphs[4]);
   392     virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
   393         return true;
   394     }
   395     virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
   396         return true;
   397     }
   399     // Access to raw font table data (needed for Harfbuzz):
   400     // returns a pointer to data owned by the fontEntry or the OS,
   401     // which will remain valid until the blob is destroyed.
   402     // The data MUST be treated as read-only; we may be getting a
   403     // reference to a shared system font cache.
   404     //
   405     // The default implementation uses CopyFontTable to get the data
   406     // into a byte array, and maintains a cache of loaded tables.
   407     //
   408     // Subclasses should override this if they can provide more efficient
   409     // access than copying table data into our own buffers.
   410     //
   411     // Get blob that encapsulates a specific font table, or nullptr if
   412     // the table doesn't exist in the font.
   413     //
   414     // Caller is responsible to call hb_blob_destroy() on the returned blob
   415     // (if non-nullptr) when no longer required. For transient access to a
   416     // table, use of AutoTable (below) is generally preferred.
   417     virtual hb_blob_t *GetFontTable(uint32_t aTag);
   419     // Stack-based utility to return a specified table, automatically releasing
   420     // the blob when the AutoTable goes out of scope.
   421     class AutoTable {
   422     public:
   423         AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag)
   424         {
   425             mBlob = aFontEntry->GetFontTable(aTag);
   426         }
   427         ~AutoTable() {
   428             if (mBlob) {
   429                 hb_blob_destroy(mBlob);
   430             }
   431         }
   432         operator hb_blob_t*() const { return mBlob; }
   433     private:
   434         hb_blob_t* mBlob;
   435         // not implemented:
   436         AutoTable(const AutoTable&) MOZ_DELETE;
   437         AutoTable& operator=(const AutoTable&) MOZ_DELETE;
   438     };
   440     already_AddRefed<gfxFont> FindOrMakeFont(const gfxFontStyle *aStyle,
   441                                              bool aNeedsBold);
   443     // Get an existing font table cache entry in aBlob if it has been
   444     // registered, or return false if not.  Callers must call
   445     // hb_blob_destroy on aBlob if true is returned.
   446     //
   447     // Note that some gfxFont implementations may not call this at all,
   448     // if it is more efficient to get the table from the OS at that level.
   449     bool GetExistingFontTable(uint32_t aTag, hb_blob_t** aBlob);
   451     // Elements of aTable are transferred (not copied) to and returned in a
   452     // new hb_blob_t which is registered on the gfxFontEntry, but the initial
   453     // reference is owned by the caller.  Removing the last reference
   454     // unregisters the table from the font entry.
   455     //
   456     // Pass nullptr for aBuffer to indicate that the table is not present and
   457     // nullptr will be returned.  Also returns nullptr on OOM.
   458     hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
   459                                         FallibleTArray<uint8_t>* aTable);
   461     // Get the font's unitsPerEm from the 'head' table, in the case of an
   462     // sfnt resource. Will return kInvalidUPEM for non-sfnt fonts,
   463     // if present on the platform.
   464     uint16_t UnitsPerEm();
   465     enum {
   466         kMinUPEM = 16,    // Limits on valid unitsPerEm range, from the
   467         kMaxUPEM = 16384, // OpenType spec
   468         kInvalidUPEM = uint16_t(-1)
   469     };
   471     // Shaper face accessors:
   472     // NOTE that harfbuzz and graphite handle ownership/lifetime of the face
   473     // object in completely different ways.
   475     // Get HarfBuzz face corresponding to this font file.
   476     // Caller must release with hb_face_destroy() when finished with it,
   477     // and the font entry will be notified via ForgetHBFace.
   478     hb_face_t* GetHBFace();
   479     virtual void ForgetHBFace();
   481     // Get Graphite face corresponding to this font file.
   482     // Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
   483     gr_face* GetGrFace();
   484     virtual void ReleaseGrFace(gr_face* aFace);
   486     // Release any SVG-glyphs document this font may have loaded.
   487     void DisconnectSVG();
   489     // Called to notify that aFont is being destroyed. Needed when we're tracking
   490     // the fonts belonging to this font entry.
   491     void NotifyFontDestroyed(gfxFont* aFont);
   493     // For memory reporting
   494     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   495                                         FontListSizes* aSizes) const;
   496     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   497                                         FontListSizes* aSizes) const;
   499     // Used when checking for complex script support, to mask off cmap ranges
   500     struct ScriptRange {
   501         uint32_t         rangeStart;
   502         uint32_t         rangeEnd;
   503         hb_tag_t         tags[3]; // one or two OpenType script tags to check,
   504                                   // plus a NULL terminator
   505     };
   507     bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags);
   509     nsString         mName;
   510     nsString         mFamilyName;
   512     bool             mItalic      : 1;
   513     bool             mFixedPitch  : 1;
   514     bool             mIsProxy     : 1;
   515     bool             mIsValid     : 1;
   516     bool             mIsBadUnderlineFont : 1;
   517     bool             mIsUserFont  : 1;
   518     bool             mIsLocalUserFont  : 1;
   519     bool             mStandardFace : 1;
   520     bool             mSymbolFont  : 1;
   521     bool             mIgnoreGDEF  : 1;
   522     bool             mIgnoreGSUB  : 1;
   523     bool             mSVGInitialized : 1;
   524     bool             mMathInitialized : 1;
   525     bool             mHasSpaceFeaturesInitialized : 1;
   526     bool             mHasSpaceFeatures : 1;
   527     bool             mHasSpaceFeaturesKerning : 1;
   528     bool             mHasSpaceFeaturesNonKerning : 1;
   529     bool             mSkipDefaultFeatureSpaceCheck : 1;
   530     bool             mHasGraphiteTables : 1;
   531     bool             mCheckedForGraphiteTables : 1;
   532     bool             mHasCmapTable : 1;
   533     bool             mGrFaceInitialized : 1;
   535     // bitvector of substitution space features per script, one each
   536     // for default and non-default features
   537     uint32_t         mDefaultSubSpaceFeatures[(MOZ_NUM_SCRIPT_CODES + 31) / 32];
   538     uint32_t         mNonDefaultSubSpaceFeatures[(MOZ_NUM_SCRIPT_CODES + 31) / 32];
   540     uint16_t         mWeight;
   541     int16_t          mStretch;
   543     nsRefPtr<gfxCharacterMap> mCharacterMap;
   544     uint32_t         mUVSOffset;
   545     nsAutoArrayPtr<uint8_t> mUVSData;
   546     nsAutoPtr<gfxUserFontData> mUserFontData;
   547     nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
   548     // list of gfxFonts that are using SVG glyphs
   549     nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
   550     nsAutoPtr<gfxMathTable> mMathTable;
   551     nsTArray<gfxFontFeature> mFeatureSettings;
   552     uint32_t         mLanguageOverride;
   554 protected:
   555     friend class gfxPlatformFontList;
   556     friend class gfxMacPlatformFontList;
   557     friend class gfxUserFcFontEntry;
   558     friend class gfxFontFamily;
   559     friend class gfxSingleFaceMacFontFamily;
   561     gfxFontEntry();
   563     // Protected destructor, to discourage deletion outside of Release():
   564     virtual ~gfxFontEntry();
   566     virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) {
   567         NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
   568         return nullptr;
   569     }
   571     virtual void CheckForGraphiteTables();
   573     // Copy a font table into aBuffer.
   574     // The caller will be responsible for ownership of the data.
   575     virtual nsresult CopyFontTable(uint32_t aTableTag,
   576                                    FallibleTArray<uint8_t>& aBuffer) {
   577         NS_NOTREACHED("forgot to override either GetFontTable or CopyFontTable?");
   578         return NS_ERROR_FAILURE;
   579     }
   581     // Return a blob that wraps a table found within a buffer of font data.
   582     // The blob does NOT own its data; caller guarantees that the buffer
   583     // will remain valid at least as long as the blob.
   584     // Returns null if the specified table is not found.
   585     // This method assumes aFontData is valid 'sfnt' data; before using this,
   586     // caller is responsible to do any sanitization/validation necessary.
   587     hb_blob_t* GetTableFromFontData(const void* aFontData, uint32_t aTableTag);
   589     // lookup the cmap in cached font data
   590     virtual already_AddRefed<gfxCharacterMap>
   591     GetCMAPFromFontInfo(FontInfoData *aFontInfoData,
   592                         uint32_t& aUVSOffset,
   593                         bool& aSymbolFont);
   595     // Font's unitsPerEm from the 'head' table, if available (will be set to
   596     // kInvalidUPEM for non-sfnt font formats)
   597     uint16_t mUnitsPerEm;
   599     // Shaper-specific face objects, shared by all instantiations of the same
   600     // physical font, regardless of size.
   601     // Usually, only one of these will actually be created for any given font
   602     // entry, depending on the font tables that are present.
   604     // hb_face_t is refcounted internally, so each shaper that's using it will
   605     // bump the ref count when it acquires the face, and "destroy" (release) it
   606     // in its destructor. The font entry has only this non-owning reference to
   607     // the face; when the face is deleted, it will tell the font entry to forget
   608     // it, so that a new face will be created next time it is needed.
   609     hb_face_t* mHBFace;
   611     static hb_blob_t* HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData);
   613     // Callback that the hb_face will use to tell us when it is being deleted.
   614     static void HBFaceDeletedCallback(void *aUserData);
   616     // gr_face is -not- refcounted, so it will be owned directly by the font
   617     // entry, and we'll keep a count of how many references we've handed out;
   618     // each shaper is responsible to call ReleaseGrFace on its entry when
   619     // finished with it, so that we know when it can be deleted.
   620     gr_face*   mGrFace;
   622     // hashtable to map raw table data ptr back to its owning blob, for use by
   623     // graphite table-release callback
   624     nsDataHashtable<nsPtrHashKey<const void>,void*>* mGrTableMap;
   626     // number of current users of this entry's mGrFace
   627     nsrefcnt mGrFaceRefCnt;
   629     static const void* GrGetTable(const void *aAppFaceHandle,
   630                                   unsigned int aName,
   631                                   size_t *aLen);
   632     static void GrReleaseTable(const void *aAppFaceHandle,
   633                                const void *aTableBuffer);
   635 private:
   636     /**
   637      * Font table hashtable, to support GetFontTable for harfbuzz.
   638      *
   639      * The harfbuzz shaper (and potentially other clients) needs access to raw
   640      * font table data. This needs to be cached so that it can be used
   641      * repeatedly (each time we construct a text run; in some cases, for
   642      * each character/glyph within the run) without re-fetching large tables
   643      * every time.
   644      * 
   645      * Because we may instantiate many gfxFonts for the same physical font
   646      * file (at different sizes), we should ensure that they can share a
   647      * single cached copy of the font tables. To do this, we implement table
   648      * access and sharing on the fontEntry rather than the font itself.
   649      *
   650      * The default implementation uses GetFontTable() to read font table
   651      * data into byte arrays, and wraps them in blobs which are registered in
   652      * a hashtable.  The hashtable can then return pre-existing blobs to
   653      * harfbuzz.
   654      *
   655      * Harfbuzz will "destroy" the blobs when it is finished with them.  When
   656      * the last blob reference is removed, the FontTableBlobData user data
   657      * will remove the blob from the hashtable if still registered.
   658      */
   660     class FontTableBlobData;
   662     /**
   663      * FontTableHashEntry manages the entries of hb_blob_t's containing font
   664      * table data.
   665      *
   666      * This is used to share font tables across fonts with the same
   667      * font entry (but different sizes) for use by HarfBuzz.  The hashtable
   668      * does not own a strong reference to the blob, but keeps a weak pointer,
   669      * managed by FontTableBlobData.  Similarly FontTableBlobData keeps only a
   670      * weak pointer to the hashtable, managed by FontTableHashEntry.
   671      */
   673     class FontTableHashEntry : public nsUint32HashKey
   674     {
   675     public:
   676         // Declarations for nsTHashtable
   678         typedef nsUint32HashKey KeyClass;
   679         typedef KeyClass::KeyType KeyType;
   680         typedef KeyClass::KeyTypePointer KeyTypePointer;
   682         FontTableHashEntry(KeyTypePointer aTag)
   683             : KeyClass(aTag)
   684             , mSharedBlobData(nullptr)
   685             , mBlob(nullptr)
   686         { }
   688         // NOTE: This assumes the new entry belongs to the same hashtable as
   689         // the old, because the mHashtable pointer in mSharedBlobData (if
   690         // present) will not be updated.
   691         FontTableHashEntry(FontTableHashEntry&& toMove)
   692             : KeyClass(mozilla::Move(toMove))
   693             , mSharedBlobData(mozilla::Move(toMove.mSharedBlobData))
   694             , mBlob(mozilla::Move(toMove.mBlob))
   695         {
   696             toMove.mSharedBlobData = nullptr;
   697             toMove.mBlob = nullptr;
   698         }
   700         ~FontTableHashEntry() { Clear(); }
   702         // FontTable/Blob API
   704         // Transfer (not copy) elements of aTable to a new hb_blob_t and
   705         // return ownership to the caller.  A weak reference to the blob is
   706         // recorded in the hashtable entry so that others may use the same
   707         // table.
   708         hb_blob_t *
   709         ShareTableAndGetBlob(FallibleTArray<uint8_t>& aTable,
   710                              nsTHashtable<FontTableHashEntry> *aHashtable);
   712         // Return a strong reference to the blob.
   713         // Callers must hb_blob_destroy the returned blob.
   714         hb_blob_t *GetBlob() const;
   716         void Clear();
   718         static size_t
   719         SizeOfEntryExcludingThis(FontTableHashEntry *aEntry,
   720                                  mozilla::MallocSizeOf aMallocSizeOf,
   721                                  void* aUserArg);
   723     private:
   724         static void DeleteFontTableBlobData(void *aBlobData);
   725         // not implemented
   726         FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
   728         FontTableBlobData *mSharedBlobData;
   729         hb_blob_t *mBlob;
   730     };
   732     nsAutoPtr<nsTHashtable<FontTableHashEntry> > mFontTableCache;
   734     gfxFontEntry(const gfxFontEntry&);
   735     gfxFontEntry& operator=(const gfxFontEntry&);
   736 };
   739 // used when iterating over all fonts looking for a match for a given character
   740 struct GlobalFontMatch {
   741     GlobalFontMatch(const uint32_t aCharacter,
   742                     int32_t aRunScript,
   743                     const gfxFontStyle *aStyle) :
   744         mCh(aCharacter), mRunScript(aRunScript), mStyle(aStyle),
   745         mMatchRank(0), mCount(0), mCmapsTested(0)
   746         {
   748         }
   750     const uint32_t         mCh;          // codepoint to be matched
   751     int32_t                mRunScript;   // Unicode script for the codepoint
   752     const gfxFontStyle*    mStyle;       // style to match
   753     int32_t                mMatchRank;   // metric indicating closest match
   754     nsRefPtr<gfxFontEntry> mBestMatch;   // current best match
   755     nsRefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
   756     uint32_t               mCount;       // number of fonts matched
   757     uint32_t               mCmapsTested; // number of cmaps tested
   758 };
   760 class gfxFontFamily {
   761 public:
   762     NS_INLINE_DECL_REFCOUNTING(gfxFontFamily)
   764     gfxFontFamily(const nsAString& aName) :
   765         mName(aName),
   766         mOtherFamilyNamesInitialized(false),
   767         mHasOtherFamilyNames(false),
   768         mFaceNamesInitialized(false),
   769         mHasStyles(false),
   770         mIsSimpleFamily(false),
   771         mIsBadUnderlineFamily(false),
   772         mFamilyCharacterMapInitialized(false),
   773         mSkipDefaultFeatureSpaceCheck(false)
   774         { }
   776     const nsString& Name() { return mName; }
   778     virtual void LocalizedName(nsAString& aLocalizedName);
   779     virtual bool HasOtherFamilyNames();
   781     nsTArray<nsRefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
   783     void AddFontEntry(nsRefPtr<gfxFontEntry> aFontEntry) {
   784         // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
   785         // of Times New Roman, because of buggy table in those fonts
   786         if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
   787             Name().EqualsLiteral("Times New Roman"))
   788         {
   789             aFontEntry->mIgnoreGDEF = true;
   790         }
   791         aFontEntry->mFamilyName = Name();
   792         aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
   793         mAvailableFonts.AppendElement(aFontEntry);
   794     }
   796     // note that the styles for this family have been added
   797     bool HasStyles() { return mHasStyles; }
   798     void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
   800     // choose a specific face to match a style using CSS font matching
   801     // rules (weight matching occurs here).  may return a face that doesn't
   802     // precisely match (e.g. normal face when no italic face exists).
   803     // aNeedsSyntheticBold is set to true when synthetic bolding is
   804     // needed, false otherwise
   805     gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle, 
   806                                    bool& aNeedsSyntheticBold);
   808     // checks for a matching font within the family
   809     // used as part of the font fallback process
   810     void FindFontForChar(GlobalFontMatch *aMatchData);
   812     // checks all fonts for a matching font within the family
   813     void SearchAllFontsForChar(GlobalFontMatch *aMatchData);
   815     // read in other family names, if any, and use functor to add each into cache
   816     virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
   818     // helper method for reading localized family names from the name table
   819     // of a single face
   820     static void ReadOtherFamilyNamesForFace(const nsAString& aFamilyName,
   821                                             const char *aNameData,
   822                                             uint32_t aDataLength,
   823                                             nsTArray<nsString>& aOtherFamilyNames,
   824                                             bool useFullName);
   826     // set when other family names have been read in
   827     void SetOtherFamilyNamesInitialized() {
   828         mOtherFamilyNamesInitialized = true;
   829     }
   831     // read in other localized family names, fullnames and Postscript names
   832     // for all faces and append to lookup tables
   833     virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
   834                                bool aNeedFullnamePostscriptNames,
   835                                FontInfoData *aFontInfoData = nullptr);
   837     // find faces belonging to this family (platform implementations override this;
   838     // should be made pure virtual once all subclasses have been updated)
   839     virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) { }
   841     // search for a specific face using the Postscript name
   842     gfxFontEntry* FindFont(const nsAString& aPostscriptName);
   844     // read in cmaps for all the faces
   845     void ReadAllCMAPs(FontInfoData *aFontInfoData = nullptr);
   847     bool TestCharacterMap(uint32_t aCh) {
   848         if (!mFamilyCharacterMapInitialized) {
   849             ReadAllCMAPs();
   850         }
   851         return mFamilyCharacterMap.test(aCh);
   852     }
   854     void ResetCharacterMap() {
   855         mFamilyCharacterMap.reset();
   856         mFamilyCharacterMapInitialized = false;
   857     }
   859     // mark this family as being in the "bad" underline offset blacklist
   860     void SetBadUnderlineFamily() {
   861         mIsBadUnderlineFamily = true;
   862         if (mHasStyles) {
   863             SetBadUnderlineFonts();
   864         }
   865     }
   867     bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
   869     // sort available fonts to put preferred (standard) faces towards the end
   870     void SortAvailableFonts();
   872     // check whether the family fits into the simple 4-face model,
   873     // so we can use simplified style-matching;
   874     // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
   875     void CheckForSimpleFamily();
   877     // For memory reporter
   878     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   879                                         FontListSizes* aSizes) const;
   880     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   881                                         FontListSizes* aSizes) const;
   883     // Only used for debugging checks - does a linear search
   884     bool ContainsFace(gfxFontEntry* aFontEntry) {
   885         uint32_t i, numFonts = mAvailableFonts.Length();
   886         for (i = 0; i < numFonts; i++) {
   887             if (mAvailableFonts[i] == aFontEntry) {
   888                 return true;
   889             }
   890         }
   891         return false;
   892     }
   894     void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
   895         mSkipDefaultFeatureSpaceCheck = aSkipCheck;
   896     }
   898 protected:
   899     // Protected destructor, to discourage deletion outside of Release():
   900     virtual ~gfxFontFamily()
   901     {
   902     }
   904     // fills in an array with weights of faces that match style,
   905     // returns whether any matching entries found
   906     virtual bool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
   907                                        bool anItalic, int16_t aStretch);
   909     bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
   910                                      hb_blob_t           *aNameTable,
   911                                      bool                 useFullName = false);
   913     // set whether this font family is in "bad" underline offset blacklist.
   914     void SetBadUnderlineFonts() {
   915         uint32_t i, numFonts = mAvailableFonts.Length();
   916         for (i = 0; i < numFonts; i++) {
   917             if (mAvailableFonts[i]) {
   918                 mAvailableFonts[i]->mIsBadUnderlineFont = true;
   919             }
   920         }
   921     }
   923     nsString mName;
   924     nsTArray<nsRefPtr<gfxFontEntry> >  mAvailableFonts;
   925     gfxSparseBitSet mFamilyCharacterMap;
   926     bool mOtherFamilyNamesInitialized : 1;
   927     bool mHasOtherFamilyNames : 1;
   928     bool mFaceNamesInitialized : 1;
   929     bool mHasStyles : 1;
   930     bool mIsSimpleFamily : 1;
   931     bool mIsBadUnderlineFamily : 1;
   932     bool mFamilyCharacterMapInitialized : 1;
   933     bool mSkipDefaultFeatureSpaceCheck : 1;
   935     enum {
   936         // for "simple" families, the faces are stored in mAvailableFonts
   937         // with fixed positions:
   938         kRegularFaceIndex    = 0,
   939         kBoldFaceIndex       = 1,
   940         kItalicFaceIndex     = 2,
   941         kBoldItalicFaceIndex = 3,
   942         // mask values for selecting face with bold and/or italic attributes
   943         kBoldMask   = 0x01,
   944         kItalicMask = 0x02
   945     };
   946 };
   948 struct gfxTextRange {
   949     enum {
   950         // flags for recording the kind of font-matching that was used
   951         kFontGroup      = 0x0001,
   952         kPrefsFallback  = 0x0002,
   953         kSystemFallback = 0x0004
   954     };
   955     gfxTextRange(uint32_t aStart, uint32_t aEnd,
   956                  gfxFont* aFont, uint8_t aMatchType)
   957         : start(aStart),
   958           end(aEnd),
   959           font(aFont),
   960           matchType(aMatchType)
   961     { }
   962     uint32_t Length() const { return end - start; }
   963     uint32_t start, end;
   964     nsRefPtr<gfxFont> font;
   965     uint8_t matchType;
   966 };
   969 /**
   970  * Font cache design:
   971  * 
   972  * The mFonts hashtable contains most fonts, indexed by (gfxFontEntry*, style).
   973  * It does not add a reference to the fonts it contains.
   974  * When a font's refcount decreases to zero, instead of deleting it we
   975  * add it to our expiration tracker.
   976  * The expiration tracker tracks fonts with zero refcount. After a certain
   977  * period of time, such fonts expire and are deleted.
   978  *
   979  * We're using 3 generations with a ten-second generation interval, so
   980  * zero-refcount fonts will be deleted 20-30 seconds after their refcount
   981  * goes to zero, if timer events fire in a timely manner.
   982  *
   983  * The font cache also handles timed expiration of cached ShapedWords
   984  * for "persistent" fonts: it has a repeating timer, and notifies
   985  * each cached font to "age" its shaped words. The words will be released
   986  * by the fonts if they get aged three times without being re-used in the
   987  * meantime.
   988  *
   989  * Note that the ShapedWord timeout is much larger than the font timeout,
   990  * so that in the case of a short-lived font, we'll discard the gfxFont
   991  * completely, with all its words, and avoid the cost of aging the words
   992  * individually. That only happens with longer-lived fonts.
   993  */
   994 struct FontCacheSizes {
   995     FontCacheSizes()
   996         : mFontInstances(0), mShapedWords(0)
   997     { }
   999     size_t mFontInstances; // memory used by instances of gfxFont subclasses
  1000     size_t mShapedWords; // memory used by the per-font shapedWord caches
  1001 };
  1003 class gfxFontCache MOZ_FINAL : public nsExpirationTracker<gfxFont,3> {
  1004 public:
  1005     enum {
  1006         FONT_TIMEOUT_SECONDS = 10,
  1007         SHAPED_WORD_TIMEOUT_SECONDS = 60
  1008     };
  1010     gfxFontCache();
  1011     ~gfxFontCache();
  1013     /*
  1014      * Get the global gfxFontCache.  You must call Init() before
  1015      * calling this method --- the result will not be null.
  1016      */
  1017     static gfxFontCache* GetCache() {
  1018         return gGlobalCache;
  1021     static nsresult Init();
  1022     // It's OK to call this even if Init() has not been called.
  1023     static void Shutdown();
  1025     // Look up a font in the cache. Returns an addrefed pointer, or null
  1026     // if there's nothing matching in the cache
  1027     already_AddRefed<gfxFont> Lookup(const gfxFontEntry *aFontEntry,
  1028                                      const gfxFontStyle *aStyle);
  1029     // We created a new font (presumably because Lookup returned null);
  1030     // put it in the cache. The font's refcount should be nonzero. It is
  1031     // allowable to add a new font even if there is one already in the
  1032     // cache with the same key; we'll forget about the old one.
  1033     void AddNew(gfxFont *aFont);
  1035     // The font's refcount has gone to zero; give ownership of it to
  1036     // the cache. We delete it if it's not acquired again after a certain
  1037     // amount of time.
  1038     void NotifyReleased(gfxFont *aFont);
  1040     // This gets called when the timeout has expired on a zero-refcount
  1041     // font; we just delete it.
  1042     virtual void NotifyExpired(gfxFont *aFont);
  1044     // Cleans out the hashtable and removes expired fonts waiting for cleanup.
  1045     // Other gfxFont objects may be still in use but they will be pushed
  1046     // into the expiration queues and removed.
  1047     void Flush() {
  1048         mFonts.Clear();
  1049         AgeAllGenerations();
  1052     void FlushShapedWordCaches() {
  1053         mFonts.EnumerateEntries(ClearCachedWordsForFont, nullptr);
  1056     void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
  1057                                 FontCacheSizes* aSizes) const;
  1058     void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
  1059                                 FontCacheSizes* aSizes) const;
  1061 protected:
  1062     class MemoryReporter MOZ_FINAL : public nsIMemoryReporter
  1064     public:
  1065         NS_DECL_ISUPPORTS
  1066         NS_DECL_NSIMEMORYREPORTER
  1067     };
  1069     // Observer for notifications that the font cache cares about
  1070     class Observer MOZ_FINAL
  1071         : public nsIObserver
  1073     public:
  1074         NS_DECL_ISUPPORTS
  1075         NS_DECL_NSIOBSERVER
  1076     };
  1078     void DestroyFont(gfxFont *aFont);
  1080     static gfxFontCache *gGlobalCache;
  1082     struct Key {
  1083         const gfxFontEntry* mFontEntry;
  1084         const gfxFontStyle* mStyle;
  1085         Key(const gfxFontEntry* aFontEntry, const gfxFontStyle* aStyle)
  1086             : mFontEntry(aFontEntry), mStyle(aStyle) {}
  1087     };
  1089     class HashEntry : public PLDHashEntryHdr {
  1090     public:
  1091         typedef const Key& KeyType;
  1092         typedef const Key* KeyTypePointer;
  1094         // When constructing a new entry in the hashtable, we'll leave this
  1095         // blank. The caller of Put() will fill this in.
  1096         HashEntry(KeyTypePointer aStr) : mFont(nullptr) { }
  1097         HashEntry(const HashEntry& toCopy) : mFont(toCopy.mFont) { }
  1098         ~HashEntry() { }
  1100         bool KeyEquals(const KeyTypePointer aKey) const;
  1101         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
  1102         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
  1103             return mozilla::HashGeneric(aKey->mStyle->Hash(), aKey->mFontEntry);
  1105         enum { ALLOW_MEMMOVE = true };
  1107         gfxFont* mFont;
  1108     };
  1110     static size_t AddSizeOfFontEntryExcludingThis(HashEntry* aHashEntry,
  1111                                                   mozilla::MallocSizeOf aMallocSizeOf,
  1112                                                   void* aUserArg);
  1114     nsTHashtable<HashEntry> mFonts;
  1116     static PLDHashOperator ClearCachedWordsForFont(HashEntry* aHashEntry, void*);
  1117     static PLDHashOperator AgeCachedWordsForFont(HashEntry* aHashEntry, void*);
  1118     static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
  1119     nsCOMPtr<nsITimer>      mWordCacheExpirationTimer;
  1120 };
  1122 class gfxTextPerfMetrics {
  1123 public:
  1125     struct TextCounts {
  1126         uint32_t    numContentTextRuns;
  1127         uint32_t    numChromeTextRuns;
  1128         uint32_t    numChars;
  1129         uint32_t    maxTextRunLen;
  1130         uint32_t    wordCacheSpaceRules;
  1131         uint32_t    wordCacheLong;
  1132         uint32_t    wordCacheHit;
  1133         uint32_t    wordCacheMiss;
  1134         uint32_t    fallbackPrefs;
  1135         uint32_t    fallbackSystem;
  1136         uint32_t    textrunConst;
  1137         uint32_t    textrunDestr;
  1138     };
  1140     uint32_t reflowCount;
  1142     // counts per reflow operation
  1143     TextCounts current;
  1145     // totals for the lifetime of a document
  1146     TextCounts cumulative;
  1148     gfxTextPerfMetrics() {
  1149         memset(this, 0, sizeof(gfxTextPerfMetrics));
  1152     // add current totals to cumulative ones
  1153     void Accumulate() {
  1154         if (current.numChars == 0) {
  1155             return;
  1157         cumulative.numContentTextRuns += current.numContentTextRuns;
  1158         cumulative.numChromeTextRuns += current.numChromeTextRuns;
  1159         cumulative.numChars += current.numChars;
  1160         if (current.maxTextRunLen > cumulative.maxTextRunLen) {
  1161             cumulative.maxTextRunLen = current.maxTextRunLen;
  1163         cumulative.wordCacheSpaceRules += current.wordCacheSpaceRules;
  1164         cumulative.wordCacheLong += current.wordCacheLong;
  1165         cumulative.wordCacheHit += current.wordCacheHit;
  1166         cumulative.wordCacheMiss += current.wordCacheMiss;
  1167         cumulative.fallbackPrefs += current.fallbackPrefs;
  1168         cumulative.fallbackSystem += current.fallbackSystem;
  1169         cumulative.textrunConst += current.textrunConst;
  1170         cumulative.textrunDestr += current.textrunDestr;
  1171         memset(&current, 0, sizeof(current));
  1173 };
  1175 class gfxTextRunFactory {
  1176     NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory)
  1178 public:
  1179     // Flags in the mask 0xFFFF0000 are reserved for textrun clients
  1180     // Flags in the mask 0x0000F000 are reserved for per-platform fonts
  1181     // Flags in the mask 0x00000FFF are set by the textrun creator.
  1182     enum {
  1183         CACHE_TEXT_FLAGS    = 0xF0000000,
  1184         USER_TEXT_FLAGS     = 0x0FFF0000,
  1185         PLATFORM_TEXT_FLAGS = 0x0000F000,
  1186         TEXTRUN_TEXT_FLAGS  = 0x00000FFF,
  1187         SETTABLE_FLAGS      = CACHE_TEXT_FLAGS | USER_TEXT_FLAGS,
  1189         /**
  1190          * When set, the text string pointer used to create the text run
  1191          * is guaranteed to be available during the lifetime of the text run.
  1192          */
  1193         TEXT_IS_PERSISTENT           = 0x0001,
  1194         /**
  1195          * When set, the text is known to be all-ASCII (< 128).
  1196          */
  1197         TEXT_IS_ASCII                = 0x0002,
  1198         /**
  1199          * When set, the text is RTL.
  1200          */
  1201         TEXT_IS_RTL                  = 0x0004,
  1202         /**
  1203          * When set, spacing is enabled and the textrun needs to call GetSpacing
  1204          * on the spacing provider.
  1205          */
  1206         TEXT_ENABLE_SPACING          = 0x0008,
  1207         /**
  1208          * When set, GetHyphenationBreaks may return true for some character
  1209          * positions, otherwise it will always return false for all characters.
  1210          */
  1211         TEXT_ENABLE_HYPHEN_BREAKS    = 0x0010,
  1212         /**
  1213          * When set, the text has no characters above 255 and it is stored
  1214          * in the textrun in 8-bit format.
  1215          */
  1216         TEXT_IS_8BIT                 = 0x0020,
  1217         /**
  1218          * When set, the RunMetrics::mBoundingBox field will be initialized
  1219          * properly based on glyph extents, in particular, glyph extents that
  1220          * overflow the standard font-box (the box defined by the ascent, descent
  1221          * and advance width of the glyph). When not set, it may just be the
  1222          * standard font-box even if glyphs overflow.
  1223          */
  1224         TEXT_NEED_BOUNDING_BOX       = 0x0040,
  1225         /**
  1226          * When set, optional ligatures are disabled. Ligatures that are
  1227          * required for legible text should still be enabled.
  1228          */
  1229         TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0080,
  1230         /**
  1231          * When set, the textrun should favour speed of construction over
  1232          * quality. This may involve disabling ligatures and/or kerning or
  1233          * other effects.
  1234          */
  1235         TEXT_OPTIMIZE_SPEED          = 0x0100,
  1236         /**
  1237          * For internal use by the memory reporter when accounting for
  1238          * storage used by textruns.
  1239          * Because the reporter may visit each textrun multiple times while
  1240          * walking the frame trees and textrun cache, it needs to mark
  1241          * textruns that have been seen so as to avoid multiple-accounting.
  1242          */
  1243         TEXT_RUN_SIZE_ACCOUNTED      = 0x0200,
  1244         /**
  1245          * When set, the textrun should discard control characters instead of
  1246          * turning them into hexboxes.
  1247          */
  1248         TEXT_HIDE_CONTROL_CHARACTERS = 0x0400,
  1250         /**
  1251          * nsTextFrameThebes sets these, but they're defined here rather than
  1252          * in nsTextFrameUtils.h because ShapedWord creation/caching also needs
  1253          * to check the _INCOMING flag
  1254          */
  1255         TEXT_TRAILING_ARABICCHAR = 0x20000000,
  1256         /**
  1257          * When set, the previous character for this textrun was an Arabic
  1258          * character.  This is used for the context detection necessary for
  1259          * bidi.numeral implementation.
  1260          */
  1261         TEXT_INCOMING_ARABICCHAR = 0x40000000,
  1263         // Set if the textrun should use the OpenType 'math' script.
  1264         TEXT_USE_MATH_SCRIPT = 0x80000000,
  1266         TEXT_UNUSED_FLAGS = 0x10000000
  1267     };
  1269     /**
  1270      * This record contains all the parameters needed to initialize a textrun.
  1271      */
  1272     struct Parameters {
  1273         // A reference context suggesting where the textrun will be rendered
  1274         gfxContext   *mContext;
  1275         // Pointer to arbitrary user data (which should outlive the textrun)
  1276         void         *mUserData;
  1277         // A description of which characters have been stripped from the original
  1278         // DOM string to produce the characters in the textrun. May be null
  1279         // if that information is not relevant.
  1280         gfxSkipChars *mSkipChars;
  1281         // A list of where linebreaks are currently placed in the textrun. May
  1282         // be null if mInitialBreakCount is zero.
  1283         uint32_t     *mInitialBreaks;
  1284         uint32_t      mInitialBreakCount;
  1285         // The ratio to use to convert device pixels to application layout units
  1286         int32_t       mAppUnitsPerDevUnit;
  1287     };
  1289 protected:
  1290     // Protected destructor, to discourage deletion outside of Release():
  1291     virtual ~gfxTextRunFactory() {}
  1292 };
  1294 /**
  1295  * This stores glyph bounds information for a particular gfxFont, at
  1296  * a particular appunits-per-dev-pixel ratio (because the compressed glyph
  1297  * width array is stored in appunits).
  1299  * We store a hashtable from glyph IDs to float bounding rects. For the
  1300  * common case where the glyph has no horizontal left bearing, and no
  1301  * y overflow above the font ascent or below the font descent, and tight
  1302  * bounding boxes are not required, we avoid storing the glyph ID in the hashtable
  1303  * and instead consult an array of 16-bit glyph XMost values (in appunits).
  1304  * This array always has an entry for the font's space glyph --- the width is
  1305  * assumed to be zero.
  1306  */
  1307 class gfxGlyphExtents {
  1308 public:
  1309     gfxGlyphExtents(int32_t aAppUnitsPerDevUnit) :
  1310         mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) {
  1311         MOZ_COUNT_CTOR(gfxGlyphExtents);
  1313     ~gfxGlyphExtents();
  1315     enum { INVALID_WIDTH = 0xFFFF };
  1317     void NotifyGlyphsChanged() {
  1318         mTightGlyphExtents.Clear();
  1321     // returns INVALID_WIDTH => not a contained glyph
  1322     // Otherwise the glyph has no before-bearing or vertical bearings,
  1323     // and the result is its width measured from the baseline origin, in
  1324     // appunits.
  1325     uint16_t GetContainedGlyphWidthAppUnits(uint32_t aGlyphID) const {
  1326         return mContainedGlyphWidths.Get(aGlyphID);
  1329     bool IsGlyphKnown(uint32_t aGlyphID) const {
  1330         return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
  1331             mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
  1334     bool IsGlyphKnownWithTightExtents(uint32_t aGlyphID) const {
  1335         return mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
  1338     // Get glyph extents; a rectangle relative to the left baseline origin
  1339     // Returns true on success. Can fail on OOM or when aContext is null
  1340     // and extents were not (successfully) prefetched.
  1341     bool GetTightGlyphExtentsAppUnits(gfxFont *aFont, gfxContext *aContext,
  1342             uint32_t aGlyphID, gfxRect *aExtents);
  1344     void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {
  1345         mContainedGlyphWidths.Set(aGlyphID, aWidth);
  1347     void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits);
  1349     int32_t GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; }
  1351     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
  1352     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
  1354 private:
  1355     class HashEntry : public nsUint32HashKey {
  1356     public:
  1357         // When constructing a new entry in the hashtable, we'll leave this
  1358         // blank. The caller of Put() will fill this in.
  1359         HashEntry(KeyTypePointer aPtr) : nsUint32HashKey(aPtr) {}
  1360         HashEntry(const HashEntry& toCopy) : nsUint32HashKey(toCopy) {
  1361           x = toCopy.x; y = toCopy.y; width = toCopy.width; height = toCopy.height;
  1364         float x, y, width, height;
  1365     };
  1367     enum { BLOCK_SIZE_BITS = 7, BLOCK_SIZE = 1 << BLOCK_SIZE_BITS }; // 128-glyph blocks
  1369     class GlyphWidths {
  1370     public:
  1371         void Set(uint32_t aIndex, uint16_t aValue);
  1372         uint16_t Get(uint32_t aIndex) const {
  1373             uint32_t block = aIndex >> BLOCK_SIZE_BITS;
  1374             if (block >= mBlocks.Length())
  1375                 return INVALID_WIDTH;
  1376             uintptr_t bits = mBlocks[block];
  1377             if (!bits)
  1378                 return INVALID_WIDTH;
  1379             uint32_t indexInBlock = aIndex & (BLOCK_SIZE - 1);
  1380             if (bits & 0x1) {
  1381                 if (GetGlyphOffset(bits) != indexInBlock)
  1382                     return INVALID_WIDTH;
  1383                 return GetWidth(bits);
  1385             uint16_t *widths = reinterpret_cast<uint16_t *>(bits);
  1386             return widths[indexInBlock];
  1389         uint32_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
  1391         ~GlyphWidths();
  1393     private:
  1394         static uint32_t GetGlyphOffset(uintptr_t aBits) {
  1395             NS_ASSERTION(aBits & 0x1, "This is really a pointer...");
  1396             return (aBits >> 1) & ((1 << BLOCK_SIZE_BITS) - 1);
  1398         static uint32_t GetWidth(uintptr_t aBits) {
  1399             NS_ASSERTION(aBits & 0x1, "This is really a pointer...");
  1400             return aBits >> (1 + BLOCK_SIZE_BITS);
  1402         static uintptr_t MakeSingle(uint32_t aGlyphOffset, uint16_t aWidth) {
  1403             return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1;
  1406         nsTArray<uintptr_t> mBlocks;
  1407     };
  1409     GlyphWidths             mContainedGlyphWidths;
  1410     nsTHashtable<HashEntry> mTightGlyphExtents;
  1411     int32_t                 mAppUnitsPerDevUnit;
  1413 private:
  1414     // not implemented:
  1415     gfxGlyphExtents(const gfxGlyphExtents& aOther) MOZ_DELETE;
  1416     gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) MOZ_DELETE;
  1417 };
  1419 /**
  1420  * gfxFontShaper
  1422  * This class implements text shaping (character to glyph mapping and
  1423  * glyph layout). There is a gfxFontShaper subclass for each text layout
  1424  * technology (uniscribe, core text, harfbuzz,....) we support.
  1426  * The shaper is responsible for setting up glyph data in gfxTextRuns.
  1428  * A generic, platform-independent shaper relies only on the standard
  1429  * gfxFont interface and can work with any concrete subclass of gfxFont.
  1431  * Platform-specific implementations designed to interface to platform
  1432  * shaping APIs such as Uniscribe or CoreText may rely on features of a
  1433  * specific font subclass to access native font references
  1434  * (such as CTFont, HFONT, DWriteFont, etc).
  1435  */
  1437 class gfxFontShaper {
  1438 public:
  1439     gfxFontShaper(gfxFont *aFont)
  1440         : mFont(aFont)
  1442         NS_ASSERTION(aFont, "shaper requires a valid font!");
  1445     virtual ~gfxFontShaper() { }
  1447     // Shape a piece of text and store the resulting glyph data into
  1448     // aShapedText. Parameters aOffset/aLength indicate the range of
  1449     // aShapedText to be updated; aLength is also the length of aText.
  1450     virtual bool ShapeText(gfxContext      *aContext,
  1451                            const char16_t *aText,
  1452                            uint32_t         aOffset,
  1453                            uint32_t         aLength,
  1454                            int32_t          aScript,
  1455                            gfxShapedText   *aShapedText) = 0;
  1457     gfxFont *GetFont() const { return mFont; }
  1459     // returns true if features exist in output, false otherwise
  1460     static bool
  1461     MergeFontFeatures(const gfxFontStyle *aStyle,
  1462                       const nsTArray<gfxFontFeature>& aFontFeatures,
  1463                       bool aDisableLigatures,
  1464                       const nsAString& aFamilyName,
  1465                       nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures);
  1467 protected:
  1468     // the font this shaper is working with
  1469     gfxFont * mFont;
  1470 };
  1472 /* a SPECIFIC single font family */
  1473 class gfxFont {
  1475     friend class gfxHarfBuzzShaper;
  1476     friend class gfxGraphiteShaper;
  1478 public:
  1479     nsrefcnt AddRef(void) {
  1480         NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
  1481         if (mExpirationState.IsTracked()) {
  1482             gfxFontCache::GetCache()->RemoveObject(this);
  1484         ++mRefCnt;
  1485         NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this));
  1486         return mRefCnt;
  1488     nsrefcnt Release(void) {
  1489         NS_PRECONDITION(0 != mRefCnt, "dup release");
  1490         --mRefCnt;
  1491         NS_LOG_RELEASE(this, mRefCnt, "gfxFont");
  1492         if (mRefCnt == 0) {
  1493             NotifyReleased();
  1494             // |this| may have been deleted.
  1495             return 0;
  1497         return mRefCnt;
  1500     int32_t GetRefCount() { return mRefCnt; }
  1502     // options to specify the kind of AA to be used when creating a font
  1503     typedef enum {
  1504         kAntialiasDefault,
  1505         kAntialiasNone,
  1506         kAntialiasGrayscale,
  1507         kAntialiasSubpixel
  1508     } AntialiasOption;
  1510 protected:
  1511     nsAutoRefCnt mRefCnt;
  1512     cairo_scaled_font_t *mScaledFont;
  1514     void NotifyReleased() {
  1515         gfxFontCache *cache = gfxFontCache::GetCache();
  1516         if (cache) {
  1517             // Don't delete just yet; return the object to the cache for
  1518             // possibly recycling within some time limit
  1519             cache->NotifyReleased(this);
  1520         } else {
  1521             // The cache may have already been shut down.
  1522             delete this;
  1526     gfxFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
  1527             AntialiasOption anAAOption = kAntialiasDefault,
  1528             cairo_scaled_font_t *aScaledFont = nullptr);
  1530 public:
  1531     virtual ~gfxFont();
  1533     bool Valid() const {
  1534         return mIsValid;
  1537     // options for the kind of bounding box to return from measurement
  1538     typedef enum {
  1539         LOOSE_INK_EXTENTS,
  1540             // A box that encloses all the painted pixels, and may
  1541             // include sidebearings and/or additional ascent/descent
  1542             // within the glyph cell even if the ink is smaller.
  1543         TIGHT_INK_EXTENTS,
  1544             // A box that tightly encloses all the painted pixels
  1545             // (although actually on Windows, at least, it may be
  1546             // slightly larger than strictly necessary because
  1547             // we can't get precise extents with ClearType).
  1548         TIGHT_HINTED_OUTLINE_EXTENTS
  1549             // A box that tightly encloses the glyph outline,
  1550             // ignoring possible antialiasing pixels that extend
  1551             // beyond this.
  1552             // NOTE: The default implementation of gfxFont::Measure(),
  1553             // which works with the glyph extents cache, does not
  1554             // differentiate between this and TIGHT_INK_EXTENTS.
  1555             // Whether the distinction is important depends on the
  1556             // antialiasing behavior of the platform; currently the
  1557             // distinction is only implemented in the gfxWindowsFont
  1558             // subclass, because of ClearType's tendency to paint
  1559             // outside the hinted outline.
  1560             // Also NOTE: it is relatively expensive to request this,
  1561             // as it does not use cached glyph extents in the font.
  1562     } BoundingBoxType;
  1564     const nsString& GetName() const { return mFontEntry->Name(); }
  1565     const gfxFontStyle *GetStyle() const { return &mStyle; }
  1567     virtual cairo_scaled_font_t* GetCairoScaledFont() { return mScaledFont; }
  1569     virtual gfxFont* CopyWithAntialiasOption(AntialiasOption anAAOption) {
  1570         // platforms where this actually matters should override
  1571         return nullptr;
  1574     virtual gfxFloat GetAdjustedSize() {
  1575         return mAdjustedSize > 0.0 ? mAdjustedSize : mStyle.size;
  1578     float FUnitsToDevUnitsFactor() const {
  1579         // check this was set up during font initialization
  1580         NS_ASSERTION(mFUnitsConvFactor > 0.0f, "mFUnitsConvFactor not valid");
  1581         return mFUnitsConvFactor;
  1584     // check whether this is an sfnt we can potentially use with harfbuzz
  1585     bool FontCanSupportHarfBuzz() {
  1586         return mFontEntry->HasCmapTable();
  1589     // check whether this is an sfnt we can potentially use with Graphite
  1590     bool FontCanSupportGraphite() {
  1591         return mFontEntry->HasGraphiteTables();
  1594     // Subclasses may choose to look up glyph ids for characters.
  1595     // If they do not override this, gfxHarfBuzzShaper will fetch the cmap
  1596     // table and use that.
  1597     virtual bool ProvidesGetGlyph() const {
  1598         return false;
  1600     // Map unicode character to glyph ID.
  1601     // Only used if ProvidesGetGlyph() returns true.
  1602     virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector) {
  1603         return 0;
  1605     // Return the horizontal advance of a glyph.
  1606     gfxFloat GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID);
  1608     // Return Azure GlyphRenderingOptions for drawing this font.
  1609     virtual mozilla::TemporaryRef<mozilla::gfx::GlyphRenderingOptions>
  1610       GetGlyphRenderingOptions() { return nullptr; }
  1612     gfxFloat SynthesizeSpaceWidth(uint32_t aCh);
  1614     // Font metrics
  1615     struct Metrics {
  1616         gfxFloat xHeight;
  1617         gfxFloat superscriptOffset;
  1618         gfxFloat subscriptOffset;
  1619         gfxFloat strikeoutSize;
  1620         gfxFloat strikeoutOffset;
  1621         gfxFloat underlineSize;
  1622         gfxFloat underlineOffset;
  1624         gfxFloat internalLeading;
  1625         gfxFloat externalLeading;
  1627         gfxFloat emHeight;
  1628         gfxFloat emAscent;
  1629         gfxFloat emDescent;
  1630         gfxFloat maxHeight;
  1631         gfxFloat maxAscent;
  1632         gfxFloat maxDescent;
  1633         gfxFloat maxAdvance;
  1635         gfxFloat aveCharWidth;
  1636         gfxFloat spaceWidth;
  1637         gfxFloat zeroOrAveCharWidth;  // width of '0', or if there is
  1638                                       // no '0' glyph in this font,
  1639                                       // equal to .aveCharWidth
  1640     };
  1641     virtual const gfxFont::Metrics& GetMetrics() = 0;
  1643     /**
  1644      * We let layout specify spacing on either side of any
  1645      * character. We need to specify both before and after
  1646      * spacing so that substring measurement can do the right things.
  1647      * These values are in appunits. They're always an integral number of
  1648      * appunits, but we specify them in floats in case very large spacing
  1649      * values are required.
  1650      */
  1651     struct Spacing {
  1652         gfxFloat mBefore;
  1653         gfxFloat mAfter;
  1654     };
  1655     /**
  1656      * Metrics for a particular string
  1657      */
  1658     struct RunMetrics {
  1659         RunMetrics() {
  1660             mAdvanceWidth = mAscent = mDescent = 0.0;
  1663         void CombineWith(const RunMetrics& aOther, bool aOtherIsOnLeft);
  1665         // can be negative (partly due to negative spacing).
  1666         // Advance widths should be additive: the advance width of the
  1667         // (offset1, length1) plus the advance width of (offset1 + length1,
  1668         // length2) should be the advance width of (offset1, length1 + length2)
  1669         gfxFloat mAdvanceWidth;
  1671         // For zero-width substrings, these must be zero!
  1672         gfxFloat mAscent;  // always non-negative
  1673         gfxFloat mDescent; // always non-negative
  1675         // Bounding box that is guaranteed to include everything drawn.
  1676         // If a tight boundingBox was requested when these metrics were
  1677         // generated, this will tightly wrap the glyphs, otherwise it is
  1678         // "loose" and may be larger than the true bounding box.
  1679         // Coordinates are relative to the baseline left origin, so typically
  1680         // mBoundingBox.y == -mAscent
  1681         gfxRect  mBoundingBox;
  1682     };
  1684     /**
  1685      * Draw a series of glyphs to aContext. The direction of aTextRun must
  1686      * be honoured.
  1687      * @param aStart the first character to draw
  1688      * @param aEnd draw characters up to here
  1689      * @param aBaselineOrigin the baseline origin; the left end of the baseline
  1690      * for LTR textruns, the right end of the baseline for RTL textruns. On return,
  1691      * this should be updated to the other end of the baseline. In application
  1692      * units, really!
  1693      * @param aSpacing spacing to insert before and after characters (for RTL
  1694      * glyphs, before-spacing is inserted to the right of characters). There
  1695      * are aEnd - aStart elements in this array, unless it's null to indicate
  1696      * that there is no spacing.
  1697      * @param aDrawMode specifies whether the fill or stroke of the glyph should be
  1698      * drawn, or if it should be drawn into the current path
  1699      * @param aContextPaint information about how to construct the fill and
  1700      * stroke pattern. Can be nullptr if we are not stroking the text, which
  1701      * indicates that the current source from aContext should be used for filling
  1703      * Callers guarantee:
  1704      * -- aStart and aEnd are aligned to cluster and ligature boundaries
  1705      * -- all glyphs use this font
  1707      * The default implementation builds a cairo glyph array and
  1708      * calls cairo_show_glyphs or cairo_glyph_path.
  1709      */
  1710     virtual void Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
  1711                       gfxContext *aContext, DrawMode aDrawMode, gfxPoint *aBaselineOrigin,
  1712                       Spacing *aSpacing, gfxTextContextPaint *aContextPaint,
  1713                       gfxTextRunDrawCallbacks *aCallbacks);
  1715     /**
  1716      * Measure a run of characters. See gfxTextRun::Metrics.
  1717      * @param aTight if false, then return the union of the glyph extents
  1718      * with the font-box for the characters (the rectangle with x=0,width=
  1719      * the advance width for the character run,y=-(font ascent), and height=
  1720      * font ascent + font descent). Otherwise, we must return as tight as possible
  1721      * an approximation to the area actually painted by glyphs.
  1722      * @param aContextForTightBoundingBox when aTight is true, this must
  1723      * be non-null.
  1724      * @param aSpacing spacing to insert before and after glyphs. The bounding box
  1725      * need not include the spacing itself, but the spacing affects the glyph
  1726      * positions. null if there is no spacing.
  1728      * Callers guarantee:
  1729      * -- aStart and aEnd are aligned to cluster and ligature boundaries
  1730      * -- all glyphs use this font
  1732      * The default implementation just uses font metrics and aTextRun's
  1733      * advances, and assumes no characters fall outside the font box. In
  1734      * general this is insufficient, because that assumption is not always true.
  1735      */
  1736     virtual RunMetrics Measure(gfxTextRun *aTextRun,
  1737                                uint32_t aStart, uint32_t aEnd,
  1738                                BoundingBoxType aBoundingBoxType,
  1739                                gfxContext *aContextForTightBoundingBox,
  1740                                Spacing *aSpacing);
  1741     /**
  1742      * Line breaks have been changed at the beginning and/or end of a substring
  1743      * of the text. Reshaping may be required; glyph updating is permitted.
  1744      * @return true if anything was changed, false otherwise
  1745      */
  1746     bool NotifyLineBreaksChanged(gfxTextRun *aTextRun,
  1747                                    uint32_t aStart, uint32_t aLength)
  1748     { return false; }
  1750     // Expiration tracking
  1751     nsExpirationState *GetExpirationState() { return &mExpirationState; }
  1753     // Get the glyphID of a space
  1754     virtual uint32_t GetSpaceGlyph() = 0;
  1756     gfxGlyphExtents *GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit);
  1758     // You need to call SetupCairoFont on the aCR just before calling this
  1759     virtual void SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID,
  1760                                    bool aNeedTight, gfxGlyphExtents *aExtents);
  1762     // This is called by the default Draw() implementation above.
  1763     virtual bool SetupCairoFont(gfxContext *aContext) = 0;
  1765     virtual bool AllowSubpixelAA() { return true; }
  1767     bool IsSyntheticBold() { return mApplySyntheticBold; }
  1769     // Amount by which synthetic bold "fattens" the glyphs:
  1770     // For size S up to a threshold size T, we use (0.25 + 3S / 4T),
  1771     // so that the result ranges from 0.25 to 1.0; thereafter,
  1772     // simply use (S / T).
  1773     gfxFloat GetSyntheticBoldOffset() {
  1774         gfxFloat size = GetAdjustedSize();
  1775         const gfxFloat threshold = 48.0;
  1776         return size < threshold ? (0.25 + 0.75 * size / threshold) :
  1777                                   (size / threshold);
  1780     gfxFontEntry *GetFontEntry() { return mFontEntry.get(); }
  1781     bool HasCharacter(uint32_t ch) {
  1782         if (!mIsValid)
  1783             return false;
  1784         return mFontEntry->HasCharacter(ch); 
  1787     uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS) {
  1788         if (!mIsValid) {
  1789             return 0;
  1791         return mFontEntry->GetUVSGlyph(aCh, aVS); 
  1794     // call the (virtual) InitTextRun method to do glyph generation/shaping,
  1795     // limiting the length of text passed by processing the run in multiple
  1796     // segments if necessary
  1797     template<typename T>
  1798     bool SplitAndInitTextRun(gfxContext *aContext,
  1799                              gfxTextRun *aTextRun,
  1800                              const T *aString,
  1801                              uint32_t aRunStart,
  1802                              uint32_t aRunLength,
  1803                              int32_t aRunScript);
  1805     // Get a ShapedWord representing the given text (either 8- or 16-bit)
  1806     // for use in setting up a gfxTextRun.
  1807     template<typename T>
  1808     gfxShapedWord* GetShapedWord(gfxContext *aContext,
  1809                                  const T *aText,
  1810                                  uint32_t aLength,
  1811                                  uint32_t aHash,
  1812                                  int32_t aRunScript,
  1813                                  int32_t aAppUnitsPerDevUnit,
  1814                                  uint32_t aFlags,
  1815                                  gfxTextPerfMetrics *aTextPerf);
  1817     // Ensure the ShapedWord cache is initialized. This MUST be called before
  1818     // any attempt to use GetShapedWord().
  1819     void InitWordCache() {
  1820         if (!mWordCache) {
  1821             mWordCache = new nsTHashtable<CacheHashEntry>;
  1825     // Called by the gfxFontCache timer to increment the age of all the words,
  1826     // so that they'll expire after a sufficient period of non-use
  1827     void AgeCachedWords() {
  1828         if (mWordCache) {
  1829             (void)mWordCache->EnumerateEntries(AgeCacheEntry, this);
  1833     // Discard all cached word records; called on memory-pressure notification.
  1834     void ClearCachedWords() {
  1835         if (mWordCache) {
  1836             mWordCache->Clear();
  1840     // Glyph rendering/geometry has changed, so invalidate data as necessary.
  1841     void NotifyGlyphsChanged();
  1843     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
  1844                                         FontCacheSizes* aSizes) const;
  1845     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
  1846                                         FontCacheSizes* aSizes) const;
  1848     typedef enum {
  1849         FONT_TYPE_DWRITE,
  1850         FONT_TYPE_GDI,
  1851         FONT_TYPE_FT2,
  1852         FONT_TYPE_MAC,
  1853         FONT_TYPE_OS2,
  1854         FONT_TYPE_CAIRO
  1855     } FontType;
  1857     virtual FontType GetType() const = 0;
  1859     virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont> GetScaledFont(mozilla::gfx::DrawTarget *aTarget)
  1860     { return gfxPlatform::GetPlatform()->GetScaledFontForFont(aTarget, this); }
  1862     bool KerningDisabled() {
  1863         return mKerningSet && !mKerningEnabled;
  1866     /**
  1867      * Subclass this object to be notified of glyph changes. Delete the object
  1868      * when no longer needed.
  1869      */
  1870     class GlyphChangeObserver {
  1871     public:
  1872         virtual ~GlyphChangeObserver()
  1874             if (mFont) {
  1875                 mFont->RemoveGlyphChangeObserver(this);
  1878         // This gets called when the gfxFont dies.
  1879         void ForgetFont() { mFont = nullptr; }
  1880         virtual void NotifyGlyphsChanged() = 0;
  1881     protected:
  1882         GlyphChangeObserver(gfxFont *aFont) : mFont(aFont)
  1884             mFont->AddGlyphChangeObserver(this);
  1886         gfxFont* mFont;
  1887     };
  1888     friend class GlyphChangeObserver;
  1890     bool GlyphsMayChange()
  1892         // Currently only fonts with SVG glyphs can have animated glyphs
  1893         return mFontEntry->TryGetSVGData(this);
  1896     static void DestroySingletons() {
  1897         delete sScriptTagToCode;
  1898         delete sDefaultFeatures;
  1901 protected:
  1902     // subclasses may provide (possibly hinted) glyph widths (in font units);
  1903     // if they do not override this, harfbuzz will use unhinted widths
  1904     // derived from the font tables
  1905     virtual bool ProvidesGlyphWidths() {
  1906         return false;
  1909     // The return value is interpreted as a horizontal advance in 16.16 fixed
  1910     // point format.
  1911     virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) {
  1912         return -1;
  1915     void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
  1916     void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
  1918     // whether font contains substitution lookups containing spaces
  1919     bool HasSubstitutionRulesWithSpaceLookups(int32_t aRunScript);
  1921     // do spaces participate in shaping rules? if so, can't used word cache
  1922     bool SpaceMayParticipateInShaping(int32_t aRunScript);
  1924     // For 8-bit text, expand to 16-bit and then call the following method.
  1925     bool ShapeText(gfxContext    *aContext,
  1926                    const uint8_t *aText,
  1927                    uint32_t       aOffset, // dest offset in gfxShapedText
  1928                    uint32_t       aLength,
  1929                    int32_t        aScript,
  1930                    gfxShapedText *aShapedText, // where to store the result
  1931                    bool           aPreferPlatformShaping = false);
  1933     // Call the appropriate shaper to generate glyphs for aText and store
  1934     // them into aShapedText.
  1935     virtual bool ShapeText(gfxContext      *aContext,
  1936                            const char16_t *aText,
  1937                            uint32_t         aOffset,
  1938                            uint32_t         aLength,
  1939                            int32_t          aScript,
  1940                            gfxShapedText   *aShapedText,
  1941                            bool             aPreferPlatformShaping = false);
  1943     // Helper to adjust for synthetic bold and set character-type flags
  1944     // in the shaped text; implementations of ShapeText should call this
  1945     // after glyph shaping has been completed.
  1946     void PostShapingFixup(gfxContext      *aContext,
  1947                           const char16_t *aText,
  1948                           uint32_t         aOffset, // position within aShapedText
  1949                           uint32_t         aLength,
  1950                           gfxShapedText   *aShapedText);
  1952     // Shape text directly into a range within a textrun, without using the
  1953     // font's word cache. Intended for use when the font has layout features
  1954     // that involve space, and therefore require shaping complete runs rather
  1955     // than isolated words, or for long strings that are inefficient to cache.
  1956     // This will split the text on "invalid" characters (tab/newline) that are
  1957     // not handled via normal shaping, but does not otherwise divide up the
  1958     // text.
  1959     template<typename T>
  1960     bool ShapeTextWithoutWordCache(gfxContext *aContext,
  1961                                    const T    *aText,
  1962                                    uint32_t    aOffset,
  1963                                    uint32_t    aLength,
  1964                                    int32_t     aScript,
  1965                                    gfxTextRun *aTextRun);
  1967     // Shape a fragment of text (a run that is known to contain only
  1968     // "valid" characters, no newlines/tabs/other control chars).
  1969     // All non-wordcache shaping goes through here; this is the function
  1970     // that will ensure we don't pass excessively long runs to the various
  1971     // platform shapers.
  1972     template<typename T>
  1973     bool ShapeFragmentWithoutWordCache(gfxContext *aContext,
  1974                                        const T    *aText,
  1975                                        uint32_t    aOffset,
  1976                                        uint32_t    aLength,
  1977                                        int32_t     aScript,
  1978                                        gfxTextRun *aTextRun);
  1980     void CheckForFeaturesInvolvingSpace();
  1982     // whether a given feature is included in feature settings from both the
  1983     // font and the style. aFeatureOn set if resolved feature value is non-zero
  1984     bool HasFeatureSet(uint32_t aFeature, bool& aFeatureOn);
  1986     // used when analyzing whether a font has space contextual lookups
  1987     static nsDataHashtable<nsUint32HashKey, int32_t> *sScriptTagToCode;
  1988     static nsTHashtable<nsUint32HashKey>             *sDefaultFeatures;
  1990     nsRefPtr<gfxFontEntry> mFontEntry;
  1992     struct CacheHashKey {
  1993         union {
  1994             const uint8_t   *mSingle;
  1995             const char16_t *mDouble;
  1996         }                mText;
  1997         uint32_t         mLength;
  1998         uint32_t         mFlags;
  1999         int32_t          mScript;
  2000         int32_t          mAppUnitsPerDevUnit;
  2001         PLDHashNumber    mHashKey;
  2002         bool             mTextIs8Bit;
  2004         CacheHashKey(const uint8_t *aText, uint32_t aLength,
  2005                      uint32_t aStringHash,
  2006                      int32_t aScriptCode, int32_t aAppUnitsPerDevUnit,
  2007                      uint32_t aFlags)
  2008             : mLength(aLength),
  2009               mFlags(aFlags),
  2010               mScript(aScriptCode),
  2011               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
  2012               mHashKey(aStringHash + aScriptCode +
  2013                   aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
  2014               mTextIs8Bit(true)
  2016             NS_ASSERTION(aFlags & gfxTextRunFactory::TEXT_IS_8BIT,
  2017                          "8-bit flag should have been set");
  2018             mText.mSingle = aText;
  2021         CacheHashKey(const char16_t *aText, uint32_t aLength,
  2022                      uint32_t aStringHash,
  2023                      int32_t aScriptCode, int32_t aAppUnitsPerDevUnit,
  2024                      uint32_t aFlags)
  2025             : mLength(aLength),
  2026               mFlags(aFlags),
  2027               mScript(aScriptCode),
  2028               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
  2029               mHashKey(aStringHash + aScriptCode +
  2030                   aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
  2031               mTextIs8Bit(false)
  2033             // We can NOT assert that TEXT_IS_8BIT is false in aFlags here,
  2034             // because this might be an 8bit-only word from a 16-bit textrun,
  2035             // in which case the text we're passed is still in 16-bit form,
  2036             // and we'll have to use an 8-to-16bit comparison in KeyEquals.
  2037             mText.mDouble = aText;
  2039     };
  2041     class CacheHashEntry : public PLDHashEntryHdr {
  2042     public:
  2043         typedef const CacheHashKey &KeyType;
  2044         typedef const CacheHashKey *KeyTypePointer;
  2046         // When constructing a new entry in the hashtable, the caller of Put()
  2047         // will fill us in.
  2048         CacheHashEntry(KeyTypePointer aKey) { }
  2049         CacheHashEntry(const CacheHashEntry& toCopy) { NS_ERROR("Should not be called"); }
  2050         ~CacheHashEntry() { }
  2052         bool KeyEquals(const KeyTypePointer aKey) const;
  2054         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
  2056         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
  2057             return aKey->mHashKey;
  2060         enum { ALLOW_MEMMOVE = true };
  2062         nsAutoPtr<gfxShapedWord> mShapedWord;
  2063     };
  2065     static size_t
  2066     WordCacheEntrySizeOfExcludingThis(CacheHashEntry*   aHashEntry,
  2067                                       mozilla::MallocSizeOf aMallocSizeOf,
  2068                                       void*             aUserArg);
  2070     nsAutoPtr<nsTHashtable<CacheHashEntry> > mWordCache;
  2072     static PLDHashOperator AgeCacheEntry(CacheHashEntry *aEntry, void *aUserData);
  2073     static const uint32_t  kShapedWordCacheMaxAge = 3;
  2075     bool                       mIsValid;
  2077     // use synthetic bolding for environments where this is not supported
  2078     // by the platform
  2079     bool                       mApplySyntheticBold;
  2081     bool                       mKerningSet;     // kerning explicitly set?
  2082     bool                       mKerningEnabled; // if set, on or off?
  2084     nsExpirationState          mExpirationState;
  2085     gfxFontStyle               mStyle;
  2086     nsAutoTArray<gfxGlyphExtents*,1> mGlyphExtentsArray;
  2087     nsAutoPtr<nsTHashtable<nsPtrHashKey<GlyphChangeObserver> > > mGlyphChangeObservers;
  2089     gfxFloat                   mAdjustedSize;
  2091     float                      mFUnitsConvFactor; // conversion factor from font units to dev units
  2093     // the AA setting requested for this font - may affect glyph bounds
  2094     AntialiasOption            mAntialiasOption;
  2096     // a copy of the font without antialiasing, if needed for separate
  2097     // measurement by mathml code
  2098     nsAutoPtr<gfxFont>         mNonAAFont;
  2100     // we may switch between these shapers on the fly, based on the script
  2101     // of the text run being shaped
  2102     nsAutoPtr<gfxFontShaper>   mPlatformShaper;
  2103     nsAutoPtr<gfxFontShaper>   mHarfBuzzShaper;
  2104     nsAutoPtr<gfxFontShaper>   mGraphiteShaper;
  2106     mozilla::RefPtr<mozilla::gfx::ScaledFont> mAzureScaledFont;
  2108     // Create a default platform text shaper for this font.
  2109     // (TODO: This should become pure virtual once all font backends have
  2110     // been updated.)
  2111     virtual void CreatePlatformShaper() { }
  2113     // Helper for subclasses that want to initialize standard metrics from the
  2114     // tables of sfnt (TrueType/OpenType) fonts.
  2115     // This will use mFUnitsConvFactor if it is already set, else compute it
  2116     // from mAdjustedSize and the unitsPerEm in the font's 'head' table.
  2117     // Returns TRUE and sets mIsValid=TRUE if successful;
  2118     // Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
  2119     // Returns FALSE if the font does not appear to be an sfnt at all,
  2120     // and should be handled (if possible) using other APIs.
  2121     bool InitMetricsFromSfntTables(Metrics& aMetrics);
  2123     // Helper to calculate various derived metrics from the results of
  2124     // InitMetricsFromSfntTables or equivalent platform code
  2125     void CalculateDerivedMetrics(Metrics& aMetrics);
  2127     // some fonts have bad metrics, this method sanitize them.
  2128     // if this font has bad underline offset, aIsBadUnderlineFont should be true.
  2129     void SanitizeMetrics(gfxFont::Metrics *aMetrics, bool aIsBadUnderlineFont);
  2131     bool RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint, DrawMode aDrawMode,
  2132                         uint32_t aGlyphId, gfxTextContextPaint *aContextPaint);
  2133     bool RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint, DrawMode aDrawMode,
  2134                         uint32_t aGlyphId, gfxTextContextPaint *aContextPaint,
  2135                         gfxTextRunDrawCallbacks *aCallbacks,
  2136                         bool& aEmittedGlyphs);
  2138     // Bug 674909. When synthetic bolding text by drawing twice, need to
  2139     // render using a pixel offset in device pixels, otherwise text
  2140     // doesn't appear bolded, it appears as if a bad text shadow exists
  2141     // when a non-identity transform exists.  Use an offset factor so that
  2142     // the second draw occurs at a constant offset in device pixels.
  2143     // This helper calculates the scale factor we need to apply to the
  2144     // synthetic-bold offset.
  2145     static double CalcXScale(gfxContext *aContext);
  2146 };
  2148 // proportion of ascent used for x-height, if unable to read value from font
  2149 #define DEFAULT_XHEIGHT_FACTOR 0.56f
  2151 /*
  2152  * gfxShapedText is an abstract superclass for gfxShapedWord and gfxTextRun.
  2153  * These are objects that store a list of zero or more glyphs for each character.
  2154  * For each glyph we store the glyph ID, the advance, and possibly x/y-offsets.
  2155  * The idea is that a string is rendered by a loop that draws each glyph
  2156  * at its designated offset from the current point, then advances the current
  2157  * point by the glyph's advance in the direction of the textrun (LTR or RTL).
  2158  * Each glyph advance is always rounded to the nearest appunit; this ensures
  2159  * consistent results when dividing the text in a textrun into multiple text
  2160  * frames (frame boundaries are always aligned to appunits). We optimize
  2161  * for the case where a character has a single glyph and zero xoffset and yoffset,
  2162  * and the glyph ID and advance are in a reasonable range so we can pack all
  2163  * necessary data into 32 bits.
  2165  * gfxFontShaper can shape text into either a gfxShapedWord (cached by a gfxFont)
  2166  * or directly into a gfxTextRun (for cases where we want to shape textruns in
  2167  * their entirety rather than using cached words, because there may be layout
  2168  * features that depend on the inter-word spaces).
  2169  */
  2170 class gfxShapedText
  2172 public:
  2173     gfxShapedText(uint32_t aLength, uint32_t aFlags,
  2174                   int32_t aAppUnitsPerDevUnit)
  2175         : mLength(aLength)
  2176         , mFlags(aFlags)
  2177         , mAppUnitsPerDevUnit(aAppUnitsPerDevUnit)
  2178     { }
  2180     virtual ~gfxShapedText() { }
  2182     /**
  2183      * This class records the information associated with a character in the
  2184      * input string. It's optimized for the case where there is one glyph
  2185      * representing that character alone.
  2187      * A character can have zero or more associated glyphs. Each glyph
  2188      * has an advance width and an x and y offset.
  2189      * A character may be the start of a cluster.
  2190      * A character may be the start of a ligature group.
  2191      * A character can be "missing", indicating that the system is unable
  2192      * to render the character.
  2194      * All characters in a ligature group conceptually share all the glyphs
  2195      * associated with the characters in a group.
  2196      */
  2197     class CompressedGlyph {
  2198     public:
  2199         CompressedGlyph() { mValue = 0; }
  2201         enum {
  2202             // Indicates that a cluster and ligature group starts at this
  2203             // character; this character has a single glyph with a reasonable
  2204             // advance and zero offsets. A "reasonable" advance
  2205             // is one that fits in the available bits (currently 12) (specified
  2206             // in appunits).
  2207             FLAG_IS_SIMPLE_GLYPH  = 0x80000000U,
  2209             // Indicates whether a linebreak is allowed before this character;
  2210             // this is a two-bit field that holds a FLAG_BREAK_TYPE_xxx value
  2211             // indicating the kind of linebreak (if any) allowed here.
  2212             FLAGS_CAN_BREAK_BEFORE = 0x60000000U,
  2214             FLAGS_CAN_BREAK_SHIFT = 29,
  2215             FLAG_BREAK_TYPE_NONE   = 0,
  2216             FLAG_BREAK_TYPE_NORMAL = 1,
  2217             FLAG_BREAK_TYPE_HYPHEN = 2,
  2219             FLAG_CHAR_IS_SPACE     = 0x10000000U,
  2221             // The advance is stored in appunits
  2222             ADVANCE_MASK  = 0x0FFF0000U,
  2223             ADVANCE_SHIFT = 16,
  2225             GLYPH_MASK = 0x0000FFFFU,
  2227             // Non-simple glyphs may or may not have glyph data in the
  2228             // corresponding mDetailedGlyphs entry. They have the following
  2229             // flag bits:
  2231             // When NOT set, indicates that this character corresponds to a
  2232             // missing glyph and should be skipped (or possibly, render the character
  2233             // Unicode value in some special way). If there are glyphs,
  2234             // the mGlyphID is actually the UTF16 character code. The bit is
  2235             // inverted so we can memset the array to zero to indicate all missing.
  2236             FLAG_NOT_MISSING              = 0x01,
  2237             FLAG_NOT_CLUSTER_START        = 0x02,
  2238             FLAG_NOT_LIGATURE_GROUP_START = 0x04,
  2240             FLAG_CHAR_IS_TAB              = 0x08,
  2241             FLAG_CHAR_IS_NEWLINE          = 0x10,
  2242             FLAG_CHAR_IS_LOW_SURROGATE    = 0x20,
  2243             CHAR_IDENTITY_FLAGS_MASK      = 0x38,
  2245             GLYPH_COUNT_MASK = 0x00FFFF00U,
  2246             GLYPH_COUNT_SHIFT = 8
  2247         };
  2249         // "Simple glyphs" have a simple glyph ID, simple advance and their
  2250         // x and y offsets are zero. Also the glyph extents do not overflow
  2251         // the font-box defined by the font ascent, descent and glyph advance width.
  2252         // These case is optimized to avoid storing DetailedGlyphs.
  2254         // Returns true if the glyph ID aGlyph fits into the compressed representation
  2255         static bool IsSimpleGlyphID(uint32_t aGlyph) {
  2256             return (aGlyph & GLYPH_MASK) == aGlyph;
  2258         // Returns true if the advance aAdvance fits into the compressed representation.
  2259         // aAdvance is in appunits.
  2260         static bool IsSimpleAdvance(uint32_t aAdvance) {
  2261             return (aAdvance & (ADVANCE_MASK >> ADVANCE_SHIFT)) == aAdvance;
  2264         bool IsSimpleGlyph() const { return (mValue & FLAG_IS_SIMPLE_GLYPH) != 0; }
  2265         uint32_t GetSimpleAdvance() const { return (mValue & ADVANCE_MASK) >> ADVANCE_SHIFT; }
  2266         uint32_t GetSimpleGlyph() const { return mValue & GLYPH_MASK; }
  2268         bool IsMissing() const { return (mValue & (FLAG_NOT_MISSING|FLAG_IS_SIMPLE_GLYPH)) == 0; }
  2269         bool IsClusterStart() const {
  2270             return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_CLUSTER_START);
  2272         bool IsLigatureGroupStart() const {
  2273             return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_LIGATURE_GROUP_START);
  2275         bool IsLigatureContinuation() const {
  2276             return (mValue & FLAG_IS_SIMPLE_GLYPH) == 0 &&
  2277                 (mValue & (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING)) ==
  2278                     (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING);
  2281         // Return true if the original character was a normal (breakable,
  2282         // trimmable) space (U+0020). Not true for other characters that
  2283         // may happen to map to the space glyph (U+00A0).
  2284         bool CharIsSpace() const {
  2285             return (mValue & FLAG_CHAR_IS_SPACE) != 0;
  2288         bool CharIsTab() const {
  2289             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_TAB) != 0;
  2291         bool CharIsNewline() const {
  2292             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_NEWLINE) != 0;
  2294         bool CharIsLowSurrogate() const {
  2295             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_LOW_SURROGATE) != 0;
  2298         uint32_t CharIdentityFlags() const {
  2299             return IsSimpleGlyph() ? 0 : (mValue & CHAR_IDENTITY_FLAGS_MASK);
  2302         void SetClusterStart(bool aIsClusterStart) {
  2303             NS_ASSERTION(!IsSimpleGlyph(),
  2304                          "can't call SetClusterStart on simple glyphs");
  2305             if (aIsClusterStart) {
  2306                 mValue &= ~FLAG_NOT_CLUSTER_START;
  2307             } else {
  2308                 mValue |= FLAG_NOT_CLUSTER_START;
  2312         uint8_t CanBreakBefore() const {
  2313             return (mValue & FLAGS_CAN_BREAK_BEFORE) >> FLAGS_CAN_BREAK_SHIFT;
  2315         // Returns FLAGS_CAN_BREAK_BEFORE if the setting changed, 0 otherwise
  2316         uint32_t SetCanBreakBefore(uint8_t aCanBreakBefore) {
  2317             NS_ASSERTION(aCanBreakBefore <= 2,
  2318                          "Bogus break-before value!");
  2319             uint32_t breakMask = (uint32_t(aCanBreakBefore) << FLAGS_CAN_BREAK_SHIFT);
  2320             uint32_t toggle = breakMask ^ (mValue & FLAGS_CAN_BREAK_BEFORE);
  2321             mValue ^= toggle;
  2322             return toggle;
  2325         CompressedGlyph& SetSimpleGlyph(uint32_t aAdvanceAppUnits, uint32_t aGlyph) {
  2326             NS_ASSERTION(IsSimpleAdvance(aAdvanceAppUnits), "Advance overflow");
  2327             NS_ASSERTION(IsSimpleGlyphID(aGlyph), "Glyph overflow");
  2328             NS_ASSERTION(!CharIdentityFlags(), "Char identity flags lost");
  2329             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) |
  2330                 FLAG_IS_SIMPLE_GLYPH |
  2331                 (aAdvanceAppUnits << ADVANCE_SHIFT) | aGlyph;
  2332             return *this;
  2334         CompressedGlyph& SetComplex(bool aClusterStart, bool aLigatureStart,
  2335                 uint32_t aGlyphCount) {
  2336             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) |
  2337                 FLAG_NOT_MISSING |
  2338                 CharIdentityFlags() |
  2339                 (aClusterStart ? 0 : FLAG_NOT_CLUSTER_START) |
  2340                 (aLigatureStart ? 0 : FLAG_NOT_LIGATURE_GROUP_START) |
  2341                 (aGlyphCount << GLYPH_COUNT_SHIFT);
  2342             return *this;
  2344         /**
  2345          * Missing glyphs are treated as ligature group starts; don't mess with
  2346          * the cluster-start flag (see bugs 618870 and 619286).
  2347          */
  2348         CompressedGlyph& SetMissing(uint32_t aGlyphCount) {
  2349             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_NOT_CLUSTER_START |
  2350                                 FLAG_CHAR_IS_SPACE)) |
  2351                 CharIdentityFlags() |
  2352                 (aGlyphCount << GLYPH_COUNT_SHIFT);
  2353             return *this;
  2355         uint32_t GetGlyphCount() const {
  2356             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
  2357             return (mValue & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT;
  2360         void SetIsSpace() {
  2361             mValue |= FLAG_CHAR_IS_SPACE;
  2363         void SetIsTab() {
  2364             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
  2365             mValue |= FLAG_CHAR_IS_TAB;
  2367         void SetIsNewline() {
  2368             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
  2369             mValue |= FLAG_CHAR_IS_NEWLINE;
  2371         void SetIsLowSurrogate() {
  2372             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
  2373             mValue |= FLAG_CHAR_IS_LOW_SURROGATE;
  2376     private:
  2377         uint32_t mValue;
  2378     };
  2380     // Accessor for the array of CompressedGlyph records, which will be in
  2381     // a different place in gfxShapedWord vs gfxTextRun
  2382     virtual CompressedGlyph *GetCharacterGlyphs() = 0;
  2384     /**
  2385      * When the glyphs for a character don't fit into a CompressedGlyph record
  2386      * in SimpleGlyph format, we use an array of DetailedGlyphs instead.
  2387      */
  2388     struct DetailedGlyph {
  2389         /** The glyphID, or the Unicode character
  2390          * if this is a missing glyph */
  2391         uint32_t mGlyphID;
  2392         /** The advance, x-offset and y-offset of the glyph, in appunits
  2393          *  mAdvance is in the text direction (RTL or LTR)
  2394          *  mXOffset is always from left to right
  2395          *  mYOffset is always from top to bottom */   
  2396         int32_t  mAdvance;
  2397         float    mXOffset, mYOffset;
  2398     };
  2400     void SetGlyphs(uint32_t aCharIndex, CompressedGlyph aGlyph,
  2401                    const DetailedGlyph *aGlyphs);
  2403     void SetMissingGlyph(uint32_t aIndex, uint32_t aChar, gfxFont *aFont);
  2405     void SetIsSpace(uint32_t aIndex) {
  2406         GetCharacterGlyphs()[aIndex].SetIsSpace();
  2409     void SetIsLowSurrogate(uint32_t aIndex) {
  2410         SetGlyphs(aIndex, CompressedGlyph().SetComplex(false, false, 0), nullptr);
  2411         GetCharacterGlyphs()[aIndex].SetIsLowSurrogate();
  2414     bool HasDetailedGlyphs() const {
  2415         return mDetailedGlyphs != nullptr;
  2418     bool IsClusterStart(uint32_t aPos) {
  2419         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2420         return GetCharacterGlyphs()[aPos].IsClusterStart();
  2423     bool IsLigatureGroupStart(uint32_t aPos) {
  2424         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2425         return GetCharacterGlyphs()[aPos].IsLigatureGroupStart();
  2428     // NOTE that this must not be called for a character offset that does
  2429     // not have any DetailedGlyph records; callers must have verified that
  2430     // GetCharacterGlyphs()[aCharIndex].GetGlyphCount() is greater than zero.
  2431     DetailedGlyph *GetDetailedGlyphs(uint32_t aCharIndex) {
  2432         NS_ASSERTION(GetCharacterGlyphs() && HasDetailedGlyphs() &&
  2433                      !GetCharacterGlyphs()[aCharIndex].IsSimpleGlyph() &&
  2434                      GetCharacterGlyphs()[aCharIndex].GetGlyphCount() > 0,
  2435                      "invalid use of GetDetailedGlyphs; check the caller!");
  2436         return mDetailedGlyphs->Get(aCharIndex);
  2439     void AdjustAdvancesForSyntheticBold(float aSynBoldOffset,
  2440                                         uint32_t aOffset, uint32_t aLength);
  2442     // Mark clusters in the CompressedGlyph records, starting at aOffset,
  2443     // based on the Unicode properties of the text in aString.
  2444     // This is also responsible to set the IsSpace flag for space characters.
  2445     void SetupClusterBoundaries(uint32_t         aOffset,
  2446                                 const char16_t *aString,
  2447                                 uint32_t         aLength);
  2448     // In 8-bit text, there won't actually be any clusters, but we still need
  2449     // the space-marking functionality.
  2450     void SetupClusterBoundaries(uint32_t       aOffset,
  2451                                 const uint8_t *aString,
  2452                                 uint32_t       aLength);
  2454     uint32_t Flags() const {
  2455         return mFlags;
  2458     bool IsRightToLeft() const {
  2459         return (Flags() & gfxTextRunFactory::TEXT_IS_RTL) != 0;
  2462     float GetDirection() const {
  2463         return IsRightToLeft() ? -1.0f : 1.0f;
  2466     bool DisableLigatures() const {
  2467         return (Flags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) != 0;
  2470     bool TextIs8Bit() const {
  2471         return (Flags() & gfxTextRunFactory::TEXT_IS_8BIT) != 0;
  2474     int32_t GetAppUnitsPerDevUnit() const {
  2475         return mAppUnitsPerDevUnit;
  2478     uint32_t GetLength() const {
  2479         return mLength;
  2482     bool FilterIfIgnorable(uint32_t aIndex, uint32_t aCh);
  2484 protected:
  2485     // Allocate aCount DetailedGlyphs for the given index
  2486     DetailedGlyph *AllocateDetailedGlyphs(uint32_t aCharIndex,
  2487                                           uint32_t aCount);
  2489     // For characters whose glyph data does not fit the "simple" glyph criteria
  2490     // in CompressedGlyph, we use a sorted array to store the association
  2491     // between the source character offset and an index into an array 
  2492     // DetailedGlyphs. The CompressedGlyph record includes a count of
  2493     // the number of DetailedGlyph records that belong to the character,
  2494     // starting at the given index.
  2495     class DetailedGlyphStore {
  2496     public:
  2497         DetailedGlyphStore()
  2498             : mLastUsed(0)
  2499         { }
  2501         // This is optimized for the most common calling patterns:
  2502         // we rarely need random access to the records, access is most commonly
  2503         // sequential through the textRun, so we record the last-used index
  2504         // and check whether the caller wants the same record again, or the
  2505         // next; if not, it's most likely we're starting over from the start
  2506         // of the run, so we check the first entry before resorting to binary
  2507         // search as a last resort.
  2508         // NOTE that this must not be called for a character offset that does
  2509         // not have any DetailedGlyph records; callers must have verified that
  2510         // mCharacterGlyphs[aOffset].GetGlyphCount() is greater than zero
  2511         // before calling this, otherwise the assertions here will fire (in a
  2512         // debug build), and we'll probably crash.
  2513         DetailedGlyph* Get(uint32_t aOffset) {
  2514             NS_ASSERTION(mOffsetToIndex.Length() > 0,
  2515                          "no detailed glyph records!");
  2516             DetailedGlyph* details = mDetails.Elements();
  2517             // check common cases (fwd iteration, initial entry, etc) first
  2518             if (mLastUsed < mOffsetToIndex.Length() - 1 &&
  2519                 aOffset == mOffsetToIndex[mLastUsed + 1].mOffset) {
  2520                 ++mLastUsed;
  2521             } else if (aOffset == mOffsetToIndex[0].mOffset) {
  2522                 mLastUsed = 0;
  2523             } else if (aOffset == mOffsetToIndex[mLastUsed].mOffset) {
  2524                 // do nothing
  2525             } else if (mLastUsed > 0 &&
  2526                        aOffset == mOffsetToIndex[mLastUsed - 1].mOffset) {
  2527                 --mLastUsed;
  2528             } else {
  2529                 mLastUsed =
  2530                     mOffsetToIndex.BinaryIndexOf(aOffset, CompareToOffset());
  2532             NS_ASSERTION(mLastUsed != nsTArray<DGRec>::NoIndex,
  2533                          "detailed glyph record missing!");
  2534             return details + mOffsetToIndex[mLastUsed].mIndex;
  2537         DetailedGlyph* Allocate(uint32_t aOffset, uint32_t aCount) {
  2538             uint32_t detailIndex = mDetails.Length();
  2539             DetailedGlyph *details = mDetails.AppendElements(aCount);
  2540             if (!details) {
  2541                 return nullptr;
  2543             // We normally set up glyph records sequentially, so the common case
  2544             // here is to append new records to the mOffsetToIndex array;
  2545             // test for that before falling back to the InsertElementSorted
  2546             // method.
  2547             if (mOffsetToIndex.Length() == 0 ||
  2548                 aOffset > mOffsetToIndex[mOffsetToIndex.Length() - 1].mOffset) {
  2549                 if (!mOffsetToIndex.AppendElement(DGRec(aOffset, detailIndex))) {
  2550                     return nullptr;
  2552             } else {
  2553                 if (!mOffsetToIndex.InsertElementSorted(DGRec(aOffset, detailIndex),
  2554                                                         CompareRecordOffsets())) {
  2555                     return nullptr;
  2558             return details;
  2561         size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
  2562             return aMallocSizeOf(this) +
  2563                 mDetails.SizeOfExcludingThis(aMallocSizeOf) +
  2564                 mOffsetToIndex.SizeOfExcludingThis(aMallocSizeOf);
  2567     private:
  2568         struct DGRec {
  2569             DGRec(const uint32_t& aOffset, const uint32_t& aIndex)
  2570                 : mOffset(aOffset), mIndex(aIndex) { }
  2571             uint32_t mOffset; // source character offset in the textrun
  2572             uint32_t mIndex;  // index where this char's DetailedGlyphs begin
  2573         };
  2575         struct CompareToOffset {
  2576             bool Equals(const DGRec& a, const uint32_t& b) const {
  2577                 return a.mOffset == b;
  2579             bool LessThan(const DGRec& a, const uint32_t& b) const {
  2580                 return a.mOffset < b;
  2582         };
  2584         struct CompareRecordOffsets {
  2585             bool Equals(const DGRec& a, const DGRec& b) const {
  2586                 return a.mOffset == b.mOffset;
  2588             bool LessThan(const DGRec& a, const DGRec& b) const {
  2589                 return a.mOffset < b.mOffset;
  2591         };
  2593         // Concatenated array of all the DetailedGlyph records needed for the
  2594         // textRun; individual character offsets are associated with indexes
  2595         // into this array via the mOffsetToIndex table.
  2596         nsTArray<DetailedGlyph>     mDetails;
  2598         // For each character offset that needs DetailedGlyphs, we record the
  2599         // index in mDetails where the list of glyphs begins. This array is
  2600         // sorted by mOffset.
  2601         nsTArray<DGRec>             mOffsetToIndex;
  2603         // Records the most recently used index into mOffsetToIndex, so that
  2604         // we can support sequential access more quickly than just doing
  2605         // a binary search each time.
  2606         nsTArray<DGRec>::index_type mLastUsed;
  2607     };
  2609     nsAutoPtr<DetailedGlyphStore>   mDetailedGlyphs;
  2611     // Number of char16_t characters and CompressedGlyph glyph records
  2612     uint32_t                        mLength;
  2614     // Shaping flags (direction, ligature-suppression)
  2615     uint32_t                        mFlags;
  2617     int32_t                         mAppUnitsPerDevUnit;
  2618 };
  2620 /*
  2621  * gfxShapedWord: an individual (space-delimited) run of text shaped with a
  2622  * particular font, without regard to external context.
  2624  * The glyph data is copied into gfxTextRuns as needed from the cache of
  2625  * ShapedWords associated with each gfxFont instance.
  2626  */
  2627 class gfxShapedWord : public gfxShapedText
  2629 public:
  2630     // Create a ShapedWord that can hold glyphs for aLength characters,
  2631     // with mCharacterGlyphs sized appropriately.
  2632     //
  2633     // Returns null on allocation failure (does NOT use infallible alloc)
  2634     // so caller must check for success.
  2635     //
  2636     // This does NOT perform shaping, so the returned word contains no
  2637     // glyph data; the caller must call gfxFont::ShapeText() with appropriate
  2638     // parameters to set up the glyphs.
  2639     static gfxShapedWord* Create(const uint8_t *aText, uint32_t aLength,
  2640                                  int32_t aRunScript,
  2641                                  int32_t aAppUnitsPerDevUnit,
  2642                                  uint32_t aFlags) {
  2643         NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
  2644                      "excessive length for gfxShapedWord!");
  2646         // Compute size needed including the mCharacterGlyphs array
  2647         // and a copy of the original text
  2648         uint32_t size =
  2649             offsetof(gfxShapedWord, mCharGlyphsStorage) +
  2650             aLength * (sizeof(CompressedGlyph) + sizeof(uint8_t));
  2651         void *storage = moz_malloc(size);
  2652         if (!storage) {
  2653             return nullptr;
  2656         // Construct in the pre-allocated storage, using placement new
  2657         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
  2658                                            aAppUnitsPerDevUnit, aFlags);
  2661     static gfxShapedWord* Create(const char16_t *aText, uint32_t aLength,
  2662                                  int32_t aRunScript,
  2663                                  int32_t aAppUnitsPerDevUnit,
  2664                                  uint32_t aFlags) {
  2665         NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
  2666                      "excessive length for gfxShapedWord!");
  2668         // In the 16-bit version of Create, if the TEXT_IS_8BIT flag is set,
  2669         // then we convert the text to an 8-bit version and call the 8-bit
  2670         // Create function instead.
  2671         if (aFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
  2672             nsAutoCString narrowText;
  2673             LossyAppendUTF16toASCII(nsDependentSubstring(aText, aLength),
  2674                                     narrowText);
  2675             return Create((const uint8_t*)(narrowText.BeginReading()),
  2676                           aLength, aRunScript, aAppUnitsPerDevUnit, aFlags);
  2679         uint32_t size =
  2680             offsetof(gfxShapedWord, mCharGlyphsStorage) +
  2681             aLength * (sizeof(CompressedGlyph) + sizeof(char16_t));
  2682         void *storage = moz_malloc(size);
  2683         if (!storage) {
  2684             return nullptr;
  2687         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
  2688                                            aAppUnitsPerDevUnit, aFlags);
  2691     // Override operator delete to properly free the object that was
  2692     // allocated via moz_malloc.
  2693     void operator delete(void* p) {
  2694         moz_free(p);
  2697     CompressedGlyph *GetCharacterGlyphs() {
  2698         return &mCharGlyphsStorage[0];
  2701     const uint8_t* Text8Bit() const {
  2702         NS_ASSERTION(TextIs8Bit(), "invalid use of Text8Bit()");
  2703         return reinterpret_cast<const uint8_t*>(mCharGlyphsStorage + GetLength());
  2706     const char16_t* TextUnicode() const {
  2707         NS_ASSERTION(!TextIs8Bit(), "invalid use of TextUnicode()");
  2708         return reinterpret_cast<const char16_t*>(mCharGlyphsStorage + GetLength());
  2711     char16_t GetCharAt(uint32_t aOffset) const {
  2712         NS_ASSERTION(aOffset < GetLength(), "aOffset out of range");
  2713         return TextIs8Bit() ?
  2714             char16_t(Text8Bit()[aOffset]) : TextUnicode()[aOffset];
  2717     int32_t Script() const {
  2718         return mScript;
  2721     void ResetAge() {
  2722         mAgeCounter = 0;
  2724     uint32_t IncrementAge() {
  2725         return ++mAgeCounter;
  2728 private:
  2729     // so that gfxTextRun can share our DetailedGlyphStore class
  2730     friend class gfxTextRun;
  2732     // Construct storage for a ShapedWord, ready to receive glyph data
  2733     gfxShapedWord(const uint8_t *aText, uint32_t aLength,
  2734                   int32_t aRunScript, int32_t aAppUnitsPerDevUnit,
  2735                   uint32_t aFlags)
  2736         : gfxShapedText(aLength, aFlags | gfxTextRunFactory::TEXT_IS_8BIT,
  2737                         aAppUnitsPerDevUnit)
  2738         , mScript(aRunScript)
  2739         , mAgeCounter(0)
  2741         memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
  2742         uint8_t *text = reinterpret_cast<uint8_t*>(&mCharGlyphsStorage[aLength]);
  2743         memcpy(text, aText, aLength * sizeof(uint8_t));
  2746     gfxShapedWord(const char16_t *aText, uint32_t aLength,
  2747                   int32_t aRunScript, int32_t aAppUnitsPerDevUnit,
  2748                   uint32_t aFlags)
  2749         : gfxShapedText(aLength, aFlags, aAppUnitsPerDevUnit)
  2750         , mScript(aRunScript)
  2751         , mAgeCounter(0)
  2753         memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
  2754         char16_t *text = reinterpret_cast<char16_t*>(&mCharGlyphsStorage[aLength]);
  2755         memcpy(text, aText, aLength * sizeof(char16_t));
  2756         SetupClusterBoundaries(0, aText, aLength);
  2759     int32_t          mScript;
  2761     uint32_t         mAgeCounter;
  2763     // The mCharGlyphsStorage array is actually a variable-size member;
  2764     // when the ShapedWord is created, its size will be increased as necessary
  2765     // to allow the proper number of glyphs to be stored.
  2766     // The original text, in either 8-bit or 16-bit form, will be stored
  2767     // immediately following the CompressedGlyphs.
  2768     CompressedGlyph  mCharGlyphsStorage[1];
  2769 };
  2771 /**
  2772  * Callback for Draw() to use when drawing text with mode
  2773  * DrawMode::GLYPH_PATH.
  2774  */
  2775 struct gfxTextRunDrawCallbacks {
  2777     /**
  2778      * Constructs a new DrawCallbacks object.
  2780      * @param aShouldPaintSVGGlyphs If true, SVG glyphs will be
  2781      *   painted and the NotifyBeforeSVGGlyphPainted/NotifyAfterSVGGlyphPainted
  2782      *   callbacks will be invoked for each SVG glyph.  If false, SVG glyphs
  2783      *   will not be painted; fallback plain glyphs are not emitted either.
  2784      */
  2785     gfxTextRunDrawCallbacks(bool aShouldPaintSVGGlyphs = false)
  2786       : mShouldPaintSVGGlyphs(aShouldPaintSVGGlyphs)
  2790     /**
  2791      * Called when a path has been emitted to the gfxContext when
  2792      * painting a text run.  This can be called any number of times,
  2793      * due to partial ligatures and intervening SVG glyphs.
  2794      */
  2795     virtual void NotifyGlyphPathEmitted() = 0;
  2797     /**
  2798      * Called just before an SVG glyph has been painted to the gfxContext.
  2799      */
  2800     virtual void NotifyBeforeSVGGlyphPainted() { }
  2802     /**
  2803      * Called just after an SVG glyph has been painted to the gfxContext.
  2804      */
  2805     virtual void NotifyAfterSVGGlyphPainted() { }
  2807     bool mShouldPaintSVGGlyphs;
  2808 };
  2810 /**
  2811  * gfxTextRun is an abstraction for drawing and measuring substrings of a run
  2812  * of text. It stores runs of positioned glyph data, each run having a single
  2813  * gfxFont. The glyphs are associated with a string of source text, and the
  2814  * gfxTextRun APIs take parameters that are offsets into that source text.
  2816  * gfxTextRuns are not refcounted. They should be deleted when no longer required.
  2818  * gfxTextRuns are mostly immutable. The only things that can change are
  2819  * inter-cluster spacing and line break placement. Spacing is always obtained
  2820  * lazily by methods that need it, it is not cached. Line breaks are stored
  2821  * persistently (insofar as they affect the shaping of glyphs; gfxTextRun does
  2822  * not actually do anything to explicitly account for line breaks). Initially
  2823  * there are no line breaks. The textrun can record line breaks before or after
  2824  * any given cluster. (Line breaks specified inside clusters are ignored.)
  2826  * It is important that zero-length substrings are handled correctly. This will
  2827  * be on the test!
  2828  */
  2829 class gfxTextRun : public gfxShapedText {
  2830 public:
  2832     // Override operator delete to properly free the object that was
  2833     // allocated via moz_malloc.
  2834     void operator delete(void* p) {
  2835         moz_free(p);
  2838     virtual ~gfxTextRun();
  2840     typedef gfxFont::RunMetrics Metrics;
  2842     // Public textrun API for general use
  2844     bool IsClusterStart(uint32_t aPos) {
  2845         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2846         return mCharacterGlyphs[aPos].IsClusterStart();
  2848     bool IsLigatureGroupStart(uint32_t aPos) {
  2849         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2850         return mCharacterGlyphs[aPos].IsLigatureGroupStart();
  2852     bool CanBreakLineBefore(uint32_t aPos) {
  2853         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2854         return mCharacterGlyphs[aPos].CanBreakBefore() ==
  2855             CompressedGlyph::FLAG_BREAK_TYPE_NORMAL;
  2857     bool CanHyphenateBefore(uint32_t aPos) {
  2858         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2859         return mCharacterGlyphs[aPos].CanBreakBefore() ==
  2860             CompressedGlyph::FLAG_BREAK_TYPE_HYPHEN;
  2863     bool CharIsSpace(uint32_t aPos) {
  2864         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2865         return mCharacterGlyphs[aPos].CharIsSpace();
  2867     bool CharIsTab(uint32_t aPos) {
  2868         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2869         return mCharacterGlyphs[aPos].CharIsTab();
  2871     bool CharIsNewline(uint32_t aPos) {
  2872         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2873         return mCharacterGlyphs[aPos].CharIsNewline();
  2875     bool CharIsLowSurrogate(uint32_t aPos) {
  2876         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
  2877         return mCharacterGlyphs[aPos].CharIsLowSurrogate();
  2880     uint32_t GetLength() { return mLength; }
  2882     // All uint32_t aStart, uint32_t aLength ranges below are restricted to
  2883     // grapheme cluster boundaries! All offsets are in terms of the string
  2884     // passed into MakeTextRun.
  2886     // All coordinates are in layout/app units
  2888     /**
  2889      * Set the potential linebreaks for a substring of the textrun. These are
  2890      * the "allow break before" points. Initially, there are no potential
  2891      * linebreaks.
  2893      * This can change glyphs and/or geometry! Some textruns' shapes
  2894      * depend on potential line breaks (e.g., title-case-converting textruns).
  2895      * This function is virtual so that those textruns can reshape themselves.
  2897      * @return true if this changed the linebreaks, false if the new line
  2898      * breaks are the same as the old
  2899      */
  2900     virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength,
  2901                                           uint8_t *aBreakBefore,
  2902                                           gfxContext *aRefContext);
  2904     /**
  2905      * Layout provides PropertyProvider objects. These allow detection of
  2906      * potential line break points and computation of spacing. We pass the data
  2907      * this way to allow lazy data acquisition; for example BreakAndMeasureText
  2908      * will want to only ask for properties of text it's actually looking at.
  2910      * NOTE that requested spacing may not actually be applied, if the textrun
  2911      * is unable to apply it in some context. Exception: spacing around a
  2912      * whitespace character MUST always be applied.
  2913      */
  2914     class PropertyProvider {
  2915     public:
  2916         // Detect hyphenation break opportunities in the given range; breaks
  2917         // not at cluster boundaries will be ignored.
  2918         virtual void GetHyphenationBreaks(uint32_t aStart, uint32_t aLength,
  2919                                           bool *aBreakBefore) = 0;
  2921         // Returns the provider's hyphenation setting, so callers can decide
  2922         // whether it is necessary to call GetHyphenationBreaks.
  2923         // Result is an NS_STYLE_HYPHENS_* value.
  2924         virtual int8_t GetHyphensOption() = 0;
  2926         // Returns the extra width that will be consumed by a hyphen. This should
  2927         // be constant for a given textrun.
  2928         virtual gfxFloat GetHyphenWidth() = 0;
  2930         typedef gfxFont::Spacing Spacing;
  2932         /**
  2933          * Get the spacing around the indicated characters. Spacing must be zero
  2934          * inside clusters. In other words, if character i is not
  2935          * CLUSTER_START, then character i-1 must have zero after-spacing and
  2936          * character i must have zero before-spacing.
  2937          */
  2938         virtual void GetSpacing(uint32_t aStart, uint32_t aLength,
  2939                                 Spacing *aSpacing) = 0;
  2941         // Returns a gfxContext that can be used to measure the hyphen glyph.
  2942         // Only called if the hyphen width is requested.
  2943         virtual already_AddRefed<gfxContext> GetContext() = 0;
  2945         // Return the appUnitsPerDevUnit value to be used when measuring.
  2946         // Only called if the hyphen width is requested.
  2947         virtual uint32_t GetAppUnitsPerDevUnit() = 0;
  2948     };
  2950     class ClusterIterator {
  2951     public:
  2952         ClusterIterator(gfxTextRun *aTextRun);
  2954         void Reset();
  2956         bool NextCluster();
  2958         uint32_t Position() const {
  2959             return mCurrentChar;
  2962         uint32_t ClusterLength() const;
  2964         gfxFloat ClusterAdvance(PropertyProvider *aProvider) const;
  2966     private:
  2967         gfxTextRun *mTextRun;
  2968         uint32_t    mCurrentChar;
  2969     };
  2971     /**
  2972      * Draws a substring. Uses only GetSpacing from aBreakProvider.
  2973      * The provided point is the baseline origin on the left of the string
  2974      * for LTR, on the right of the string for RTL.
  2975      * @param aAdvanceWidth if non-null, the advance width of the substring
  2976      * is returned here.
  2978      * Drawing should respect advance widths in the sense that for LTR runs,
  2979      * Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by
  2980      * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1 + length1, length2,
  2981      *      dirty, &provider, nullptr) should have the same effect as
  2982      * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nullptr).
  2983      * For RTL runs the rule is:
  2984      * Draw(ctx, pt, offset1 + length1, length2, dirty, &provider, &advance) followed by
  2985      * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1, length1,
  2986      *      dirty, &provider, nullptr) should have the same effect as
  2987      * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nullptr).
  2989      * Glyphs should be drawn in logical content order, which can be significant
  2990      * if they overlap (perhaps due to negative spacing).
  2991      */
  2992     void Draw(gfxContext *aContext, gfxPoint aPt,
  2993               DrawMode aDrawMode,
  2994               uint32_t aStart, uint32_t aLength,
  2995               PropertyProvider *aProvider,
  2996               gfxFloat *aAdvanceWidth, gfxTextContextPaint *aContextPaint,
  2997               gfxTextRunDrawCallbacks *aCallbacks = nullptr);
  2999     /**
  3000      * Computes the ReflowMetrics for a substring.
  3001      * Uses GetSpacing from aBreakProvider.
  3002      * @param aBoundingBoxType which kind of bounding box (loose/tight)
  3003      */
  3004     Metrics MeasureText(uint32_t aStart, uint32_t aLength,
  3005                         gfxFont::BoundingBoxType aBoundingBoxType,
  3006                         gfxContext *aRefContextForTightBoundingBox,
  3007                         PropertyProvider *aProvider);
  3009     /**
  3010      * Computes just the advance width for a substring.
  3011      * Uses GetSpacing from aBreakProvider.
  3012      */
  3013     gfxFloat GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
  3014                              PropertyProvider *aProvider);
  3016     /**
  3017      * Clear all stored line breaks for the given range (both before and after),
  3018      * and then set the line-break state before aStart to aBreakBefore and
  3019      * after the last cluster to aBreakAfter.
  3021      * We require that before and after line breaks be consistent. For clusters
  3022      * i and i+1, we require that if there is a break after cluster i, a break
  3023      * will be specified before cluster i+1. This may be temporarily violated
  3024      * (e.g. after reflowing line L and before reflowing line L+1); to handle
  3025      * these temporary violations, we say that there is a break betwen i and i+1
  3026      * if a break is specified after i OR a break is specified before i+1.
  3028      * This can change textrun geometry! The existence of a linebreak can affect
  3029      * the advance width of the cluster before the break (when kerning) or the
  3030      * geometry of one cluster before the break or any number of clusters
  3031      * after the break. (The one-cluster-before-the-break limit is somewhat
  3032      * arbitrary; if some scripts require breaking it, then we need to
  3033      * alter nsTextFrame::TrimTrailingWhitespace, perhaps drastically becase
  3034      * it could affect the layout of frames before it...)
  3036      * We return true if glyphs or geometry changed, false otherwise. This
  3037      * function is virtual so that gfxTextRun subclasses can reshape
  3038      * properly.
  3040      * @param aAdvanceWidthDelta if non-null, returns the change in advance
  3041      * width of the given range.
  3042      */
  3043     virtual bool SetLineBreaks(uint32_t aStart, uint32_t aLength,
  3044                                  bool aLineBreakBefore, bool aLineBreakAfter,
  3045                                  gfxFloat *aAdvanceWidthDelta,
  3046                                  gfxContext *aRefContext);
  3048     /**
  3049      * Finds the longest substring that will fit into the given width.
  3050      * Uses GetHyphenationBreaks and GetSpacing from aBreakProvider.
  3051      * Guarantees the following:
  3052      * -- 0 <= result <= aMaxLength
  3053      * -- result is the maximal value of N such that either
  3054      *       N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
  3055      *   OR  N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
  3056      *   OR  N == aMaxLength && GetAdvanceWidth(aStart, N) <= aWidth
  3057      * where GetAdvanceWidth assumes the effect of
  3058      * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
  3059      * -- if no such N exists, then result is the smallest N such that
  3060      *       N < aMaxLength && line break at N
  3061      *   OR  N < aMaxLength && hyphen break at N
  3062      *   OR  N == aMaxLength
  3064      * The call has the effect of
  3065      * SetLineBreaks(aStart, result, aLineBreakBefore, result < aMaxLength, aProvider)
  3066      * and the returned metrics and the invariants above reflect this.
  3068      * @param aMaxLength this can be UINT32_MAX, in which case the length used
  3069      * is up to the end of the string
  3070      * @param aLineBreakBefore set to true if and only if there is an actual
  3071      * line break at the start of this string.
  3072      * @param aSuppressInitialBreak if true, then we assume there is no possible
  3073      * linebreak before aStart. If false, then we will check the internal
  3074      * line break opportunity state before deciding whether to return 0 as the
  3075      * character to break before.
  3076      * @param aTrimWhitespace if non-null, then we allow a trailing run of
  3077      * spaces to be trimmed; the width of the space(s) will not be included in
  3078      * the measured string width for comparison with the limit aWidth, and
  3079      * trimmed spaces will not be included in returned metrics. The width
  3080      * of the trimmed spaces will be returned in aTrimWhitespace.
  3081      * Trimmed spaces are still counted in the "characters fit" result.
  3082      * @param aMetrics if non-null, we fill this in for the returned substring.
  3083      * If a hyphenation break was used, the hyphen is NOT included in the returned metrics.
  3084      * @param aBoundingBoxType whether to make the bounding box in aMetrics tight
  3085      * @param aRefContextForTightBoundingBox a reference context to get the
  3086      * tight bounding box, if requested
  3087      * @param aUsedHyphenation if non-null, records if we selected a hyphenation break
  3088      * @param aLastBreak if non-null and result is aMaxLength, we set this to
  3089      * the maximal N such that
  3090      *       N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
  3091      *   OR  N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
  3092      * or UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
  3093      * the effect of
  3094      * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
  3096      * @param aCanWordWrap true if we can break between any two grapheme
  3097      * clusters. This is set by word-wrap: break-word
  3099      * @param aBreakPriority in/out the priority of the break opportunity
  3100      * saved in the line. If we are prioritizing break opportunities, we will
  3101      * not set a break with a lower priority. @see gfxBreakPriority.
  3103      * Note that negative advance widths are possible especially if negative
  3104      * spacing is provided.
  3105      */
  3106     uint32_t BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
  3107                                  bool aLineBreakBefore, gfxFloat aWidth,
  3108                                  PropertyProvider *aProvider,
  3109                                  bool aSuppressInitialBreak,
  3110                                  gfxFloat *aTrimWhitespace,
  3111                                  Metrics *aMetrics,
  3112                                  gfxFont::BoundingBoxType aBoundingBoxType,
  3113                                  gfxContext *aRefContextForTightBoundingBox,
  3114                                  bool *aUsedHyphenation,
  3115                                  uint32_t *aLastBreak,
  3116                                  bool aCanWordWrap,
  3117                                  gfxBreakPriority *aBreakPriority);
  3119     /**
  3120      * Update the reference context.
  3121      * XXX this is a hack. New text frame does not call this. Use only
  3122      * temporarily for old text frame.
  3123      */
  3124     void SetContext(gfxContext *aContext) {}
  3126     // Utility getters
  3128     gfxFloat GetDirection() const { return (mFlags & gfxTextRunFactory::TEXT_IS_RTL) ? -1.0 : 1.0; }
  3129     void *GetUserData() const { return mUserData; }
  3130     void SetUserData(void *aUserData) { mUserData = aUserData; }
  3131     uint32_t GetFlags() const { return mFlags; }
  3132     void SetFlagBits(uint32_t aFlags) {
  3133       NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
  3134                    "Only user flags should be mutable");
  3135       mFlags |= aFlags;
  3137     void ClearFlagBits(uint32_t aFlags) {
  3138       NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
  3139                    "Only user flags should be mutable");
  3140       mFlags &= ~aFlags;
  3142     const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
  3143     gfxFontGroup *GetFontGroup() const { return mFontGroup; }
  3146     // Call this, don't call "new gfxTextRun" directly. This does custom
  3147     // allocation and initialization
  3148     static gfxTextRun *Create(const gfxTextRunFactory::Parameters *aParams,
  3149                               uint32_t aLength, gfxFontGroup *aFontGroup,
  3150                               uint32_t aFlags);
  3152     // The text is divided into GlyphRuns as necessary
  3153     struct GlyphRun {
  3154         nsRefPtr<gfxFont> mFont;   // never null
  3155         uint32_t          mCharacterOffset; // into original UTF16 string
  3156         uint8_t           mMatchType;
  3157     };
  3159     class GlyphRunIterator {
  3160     public:
  3161         GlyphRunIterator(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aLength)
  3162           : mTextRun(aTextRun), mStartOffset(aStart), mEndOffset(aStart + aLength) {
  3163             mNextIndex = mTextRun->FindFirstGlyphRunContaining(aStart);
  3165         bool NextRun();
  3166         GlyphRun *GetGlyphRun() { return mGlyphRun; }
  3167         uint32_t GetStringStart() { return mStringStart; }
  3168         uint32_t GetStringEnd() { return mStringEnd; }
  3169     private:
  3170         gfxTextRun *mTextRun;
  3171         GlyphRun   *mGlyphRun;
  3172         uint32_t    mStringStart;
  3173         uint32_t    mStringEnd;
  3174         uint32_t    mNextIndex;
  3175         uint32_t    mStartOffset;
  3176         uint32_t    mEndOffset;
  3177     };
  3179     class GlyphRunOffsetComparator {
  3180     public:
  3181         bool Equals(const GlyphRun& a,
  3182                       const GlyphRun& b) const
  3184             return a.mCharacterOffset == b.mCharacterOffset;
  3187         bool LessThan(const GlyphRun& a,
  3188                         const GlyphRun& b) const
  3190             return a.mCharacterOffset < b.mCharacterOffset;
  3192     };
  3194     friend class GlyphRunIterator;
  3195     friend class FontSelector;
  3197     // API for setting up the textrun glyphs. Should only be called by
  3198     // things that construct textruns.
  3199     /**
  3200      * We've found a run of text that should use a particular font. Call this
  3201      * only during initialization when font substitution has been computed.
  3202      * Call it before setting up the glyphs for the characters in this run;
  3203      * SetMissingGlyph requires that the correct glyphrun be installed.
  3205      * If aForceNewRun, a new glyph run will be added, even if the
  3206      * previously added run uses the same font.  If glyph runs are
  3207      * added out of strictly increasing aStartCharIndex order (via
  3208      * force), then SortGlyphRuns must be called after all glyph runs
  3209      * are added before any further operations are performed with this
  3210      * TextRun.
  3211      */
  3212     nsresult AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
  3213                          uint32_t aStartCharIndex, bool aForceNewRun);
  3214     void ResetGlyphRuns() { mGlyphRuns.Clear(); }
  3215     void SortGlyphRuns();
  3216     void SanitizeGlyphRuns();
  3218     CompressedGlyph* GetCharacterGlyphs() {
  3219         NS_ASSERTION(mCharacterGlyphs, "failed to initialize mCharacterGlyphs");
  3220         return mCharacterGlyphs;
  3223     void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, uint32_t aCharIndex);
  3225     // Set the glyph data for the given character index to the font's
  3226     // space glyph, IF this can be done as a "simple" glyph record
  3227     // (not requiring a DetailedGlyph entry). This avoids the need to call
  3228     // the font shaper and go through the shaped-word cache for most spaces.
  3229     //
  3230     // The parameter aSpaceChar is the original character code for which
  3231     // this space glyph is being used; if this is U+0020, we need to record
  3232     // that it could be trimmed at a run edge, whereas other kinds of space
  3233     // (currently just U+00A0) would not be trimmable/breakable.
  3234     //
  3235     // Returns true if it was able to set simple glyph data for the space;
  3236     // if it returns false, the caller needs to fall back to some other
  3237     // means to create the necessary (detailed) glyph data.
  3238     bool SetSpaceGlyphIfSimple(gfxFont *aFont, gfxContext *aContext,
  3239                                uint32_t aCharIndex, char16_t aSpaceChar);
  3241     // Record the positions of specific characters that layout may need to
  3242     // detect in the textrun, even though it doesn't have an explicit copy
  3243     // of the original text. These are recorded using flag bits in the
  3244     // CompressedGlyph record; if necessary, we convert "simple" glyph records
  3245     // to "complex" ones as the Tab and Newline flags are not present in
  3246     // simple CompressedGlyph records.
  3247     void SetIsTab(uint32_t aIndex) {
  3248         CompressedGlyph *g = &mCharacterGlyphs[aIndex];
  3249         if (g->IsSimpleGlyph()) {
  3250             DetailedGlyph *details = AllocateDetailedGlyphs(aIndex, 1);
  3251             details->mGlyphID = g->GetSimpleGlyph();
  3252             details->mAdvance = g->GetSimpleAdvance();
  3253             details->mXOffset = details->mYOffset = 0;
  3254             SetGlyphs(aIndex, CompressedGlyph().SetComplex(true, true, 1), details);
  3256         g->SetIsTab();
  3258     void SetIsNewline(uint32_t aIndex) {
  3259         CompressedGlyph *g = &mCharacterGlyphs[aIndex];
  3260         if (g->IsSimpleGlyph()) {
  3261             DetailedGlyph *details = AllocateDetailedGlyphs(aIndex, 1);
  3262             details->mGlyphID = g->GetSimpleGlyph();
  3263             details->mAdvance = g->GetSimpleAdvance();
  3264             details->mXOffset = details->mYOffset = 0;
  3265             SetGlyphs(aIndex, CompressedGlyph().SetComplex(true, true, 1), details);
  3267         g->SetIsNewline();
  3269     void SetIsLowSurrogate(uint32_t aIndex) {
  3270         SetGlyphs(aIndex, CompressedGlyph().SetComplex(false, false, 0), nullptr);
  3271         mCharacterGlyphs[aIndex].SetIsLowSurrogate();
  3274     /**
  3275      * Prefetch all the glyph extents needed to ensure that Measure calls
  3276      * on this textrun not requesting tight boundingBoxes will succeed. Note
  3277      * that some glyph extents might not be fetched due to OOM or other
  3278      * errors.
  3279      */
  3280     void FetchGlyphExtents(gfxContext *aRefContext);
  3282     uint32_t CountMissingGlyphs();
  3283     const GlyphRun *GetGlyphRuns(uint32_t *aNumGlyphRuns) {
  3284         *aNumGlyphRuns = mGlyphRuns.Length();
  3285         return mGlyphRuns.Elements();
  3287     // Returns the index of the GlyphRun containing the given offset.
  3288     // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
  3289     uint32_t FindFirstGlyphRunContaining(uint32_t aOffset);
  3291     // Copy glyph data from a ShapedWord into this textrun.
  3292     void CopyGlyphDataFrom(gfxShapedWord *aSource, uint32_t aStart);
  3294     // Copy glyph data for a range of characters from aSource to this
  3295     // textrun.
  3296     void CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
  3297                            uint32_t aLength, uint32_t aDest);
  3299     nsExpirationState *GetExpirationState() { return &mExpirationState; }
  3301     // Tell the textrun to release its reference to its creating gfxFontGroup
  3302     // immediately, rather than on destruction. This is used for textruns
  3303     // that are actually owned by a gfxFontGroup, so that they don't keep it
  3304     // permanently alive due to a circular reference. (The caller of this is
  3305     // taking responsibility for ensuring the textrun will not outlive its
  3306     // mFontGroup.)
  3307     void ReleaseFontGroup();
  3309     struct LigatureData {
  3310         // textrun offsets of the start and end of the containing ligature
  3311         uint32_t mLigatureStart;
  3312         uint32_t mLigatureEnd;
  3313         // appunits advance to the start of the ligature part within the ligature;
  3314         // never includes any spacing
  3315         gfxFloat mPartAdvance;
  3316         // appunits width of the ligature part; includes before-spacing
  3317         // when the part is at the start of the ligature, and after-spacing
  3318         // when the part is as the end of the ligature
  3319         gfxFloat mPartWidth;
  3321         bool mClipBeforePart;
  3322         bool mClipAfterPart;
  3323     };
  3325     // return storage used by this run, for memory reporter;
  3326     // nsTransformedTextRun needs to override this as it holds additional data
  3327     virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
  3328       MOZ_MUST_OVERRIDE;
  3329     virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
  3330       MOZ_MUST_OVERRIDE;
  3332     // Get the size, if it hasn't already been gotten, marking as it goes.
  3333     size_t MaybeSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)  {
  3334         if (mFlags & gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED) {
  3335             return 0;
  3337         mFlags |= gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
  3338         return SizeOfIncludingThis(aMallocSizeOf);
  3340     void ResetSizeOfAccountingFlags() {
  3341         mFlags &= ~gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
  3344 #ifdef DEBUG
  3345     void Dump(FILE* aOutput);
  3346 #endif
  3348 protected:
  3349     /**
  3350      * Create a textrun, and set its mCharacterGlyphs to point immediately
  3351      * after the base object; this is ONLY used in conjunction with placement
  3352      * new, after allocating a block large enough for the glyph records to
  3353      * follow the base textrun object.
  3354      */
  3355     gfxTextRun(const gfxTextRunFactory::Parameters *aParams,
  3356                uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags);
  3358     /**
  3359      * Helper for the Create() factory method to allocate the required
  3360      * glyph storage for a textrun object with the basic size aSize,
  3361      * plus room for aLength glyph records.
  3362      */
  3363     static void* AllocateStorageForTextRun(size_t aSize, uint32_t aLength);
  3365     // Pointer to the array of CompressedGlyph records; must be initialized
  3366     // when the object is constructed.
  3367     CompressedGlyph *mCharacterGlyphs;
  3369 private:
  3370     // **** general helpers **** 
  3372     // Allocate aCount DetailedGlyphs for the given index
  3373     DetailedGlyph *AllocateDetailedGlyphs(uint32_t aCharIndex, uint32_t aCount);
  3375     // Get the total advance for a range of glyphs.
  3376     int32_t GetAdvanceForGlyphs(uint32_t aStart, uint32_t aEnd);
  3378     // Spacing for characters outside the range aSpacingStart/aSpacingEnd
  3379     // is assumed to be zero; such characters are not passed to aProvider.
  3380     // This is useful to protect aProvider from being passed character indices
  3381     // it is not currently able to handle.
  3382     bool GetAdjustedSpacingArray(uint32_t aStart, uint32_t aEnd,
  3383                                    PropertyProvider *aProvider,
  3384                                    uint32_t aSpacingStart, uint32_t aSpacingEnd,
  3385                                    nsTArray<PropertyProvider::Spacing> *aSpacing);
  3387     //  **** ligature helpers ****
  3388     // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
  3389     // to handle requests that begin or end inside a ligature)
  3391     // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
  3392     LigatureData ComputeLigatureData(uint32_t aPartStart, uint32_t aPartEnd,
  3393                                      PropertyProvider *aProvider);
  3394     gfxFloat ComputePartialLigatureWidth(uint32_t aPartStart, uint32_t aPartEnd,
  3395                                          PropertyProvider *aProvider);
  3396     void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
  3397                              uint32_t aStart, uint32_t aEnd, gfxPoint *aPt,
  3398                              PropertyProvider *aProvider,
  3399                              gfxTextRunDrawCallbacks *aCallbacks);
  3400     // Advance aStart to the start of the nearest ligature; back up aEnd
  3401     // to the nearest ligature end; may result in *aStart == *aEnd
  3402     void ShrinkToLigatureBoundaries(uint32_t *aStart, uint32_t *aEnd);
  3403     // result in appunits
  3404     gfxFloat GetPartialLigatureWidth(uint32_t aStart, uint32_t aEnd, PropertyProvider *aProvider);
  3405     void AccumulatePartialLigatureMetrics(gfxFont *aFont,
  3406                                           uint32_t aStart, uint32_t aEnd,
  3407                                           gfxFont::BoundingBoxType aBoundingBoxType,
  3408                                           gfxContext *aRefContext,
  3409                                           PropertyProvider *aProvider,
  3410                                           Metrics *aMetrics);
  3412     // **** measurement helper ****
  3413     void AccumulateMetricsForRun(gfxFont *aFont, uint32_t aStart, uint32_t aEnd,
  3414                                  gfxFont::BoundingBoxType aBoundingBoxType,
  3415                                  gfxContext *aRefContext,
  3416                                  PropertyProvider *aProvider,
  3417                                  uint32_t aSpacingStart, uint32_t aSpacingEnd,
  3418                                  Metrics *aMetrics);
  3420     // **** drawing helper ****
  3421     void DrawGlyphs(gfxFont *aFont, gfxContext *aContext,
  3422                     DrawMode aDrawMode, gfxPoint *aPt,
  3423                     gfxTextContextPaint *aContextPaint, uint32_t aStart,
  3424                     uint32_t aEnd, PropertyProvider *aProvider,
  3425                     uint32_t aSpacingStart, uint32_t aSpacingEnd,
  3426                     gfxTextRunDrawCallbacks *aCallbacks);
  3428     // XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*,
  3429     // for smaller size especially in the super-common one-glyphrun case
  3430     nsAutoTArray<GlyphRun,1>        mGlyphRuns;
  3432     void             *mUserData;
  3433     gfxFontGroup     *mFontGroup; // addrefed on creation, but our reference
  3434                                   // may be released by ReleaseFontGroup()
  3435     gfxSkipChars      mSkipChars;
  3436     nsExpirationState mExpirationState;
  3438     bool              mSkipDrawing; // true if the font group we used had a user font
  3439                                     // download that's in progress, so we should hide text
  3440                                     // until the download completes (or timeout fires)
  3441     bool              mReleasedFontGroup; // we already called NS_RELEASE on
  3442                                           // mFontGroup, so don't do it again
  3443 };
  3445 class gfxFontGroup : public gfxTextRunFactory {
  3446 public:
  3447     class FamilyFace {
  3448     public:
  3449         FamilyFace() { }
  3451         FamilyFace(gfxFontFamily* aFamily, gfxFont* aFont)
  3452             : mFamily(aFamily), mFont(aFont)
  3454             NS_ASSERTION(aFont, "font pointer must not be null");
  3455             NS_ASSERTION(!aFamily ||
  3456                          aFamily->ContainsFace(aFont->GetFontEntry()),
  3457                          "font is not a member of the given family");
  3460         gfxFontFamily* Family() const { return mFamily.get(); }
  3461         gfxFont* Font() const { return mFont.get(); }
  3463     private:
  3464         nsRefPtr<gfxFontFamily> mFamily;
  3465         nsRefPtr<gfxFont>       mFont;
  3466     };
  3468     static void Shutdown(); // platform must call this to release the languageAtomService
  3470     gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet = nullptr);
  3472     virtual ~gfxFontGroup();
  3474     virtual gfxFont *GetFontAt(int32_t i) {
  3475         // If it turns out to be hard for all clients that cache font
  3476         // groups to call UpdateFontList at appropriate times, we could
  3477         // instead consider just calling UpdateFontList from someplace
  3478         // more central (such as here).
  3479         NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
  3480                      "Whoever was caching this font group should have "
  3481                      "called UpdateFontList on it");
  3482         NS_ASSERTION(mFonts.Length() > uint32_t(i) && mFonts[i].Font(), 
  3483                      "Requesting a font index that doesn't exist");
  3485         return mFonts[i].Font();
  3488     uint32_t FontListLength() const {
  3489         return mFonts.Length();
  3492     bool Equals(const gfxFontGroup& other) const {
  3493         return mFamilies.Equals(other.mFamilies) &&
  3494             mStyle.Equals(other.mStyle);
  3497     const gfxFontStyle *GetStyle() const { return &mStyle; }
  3499     virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
  3501     /**
  3502      * The listed characters should be treated as invisible and zero-width
  3503      * when creating textruns.
  3504      */
  3505     static bool IsInvalidChar(uint8_t ch);
  3506     static bool IsInvalidChar(char16_t ch);
  3508     /**
  3509      * Make a textrun for a given string.
  3510      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
  3511      * textrun will copy it.
  3512      * This calls FetchGlyphExtents on the textrun.
  3513      */
  3514     virtual gfxTextRun *MakeTextRun(const char16_t *aString, uint32_t aLength,
  3515                                     const Parameters *aParams, uint32_t aFlags);
  3516     /**
  3517      * Make a textrun for a given string.
  3518      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
  3519      * textrun will copy it.
  3520      * This calls FetchGlyphExtents on the textrun.
  3521      */
  3522     virtual gfxTextRun *MakeTextRun(const uint8_t *aString, uint32_t aLength,
  3523                                     const Parameters *aParams, uint32_t aFlags);
  3525     /**
  3526      * Textrun creation helper for clients that don't want to pass
  3527      * a full Parameters record.
  3528      */
  3529     template<typename T>
  3530     gfxTextRun *MakeTextRun(const T *aString, uint32_t aLength,
  3531                             gfxContext *aRefContext,
  3532                             int32_t aAppUnitsPerDevUnit,
  3533                             uint32_t aFlags)
  3535         gfxTextRunFactory::Parameters params = {
  3536             aRefContext, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevUnit
  3537         };
  3538         return MakeTextRun(aString, aLength, &params, aFlags);
  3541     /**
  3542      * Get the (possibly-cached) width of the hyphen character.
  3543      * The aCtx and aAppUnitsPerDevUnit parameters will be used only if
  3544      * needed to initialize the cached hyphen width; otherwise they are
  3545      * ignored.
  3546      */
  3547     gfxFloat GetHyphenWidth(gfxTextRun::PropertyProvider* aProvider);
  3549     /**
  3550      * Make a text run representing a single hyphen character.
  3551      * This will use U+2010 HYPHEN if available in the first font,
  3552      * otherwise fall back to U+002D HYPHEN-MINUS.
  3553      * The caller is responsible for deleting the returned text run
  3554      * when no longer required.
  3555      */
  3556     gfxTextRun *MakeHyphenTextRun(gfxContext *aCtx,
  3557                                   uint32_t aAppUnitsPerDevUnit);
  3559     /* helper function for splitting font families on commas and
  3560      * calling a function for each family to fill the mFonts array
  3561      */
  3562     typedef bool (*FontCreationCallback) (const nsAString& aName,
  3563                                             const nsACString& aGenericName,
  3564                                             bool aUseFontSet,
  3565                                             void *closure);
  3566     bool ForEachFont(const nsAString& aFamilies,
  3567                        nsIAtom *aLanguage,
  3568                        FontCreationCallback fc,
  3569                        void *closure);
  3570     bool ForEachFont(FontCreationCallback fc, void *closure);
  3572     /**
  3573      * Check whether a given font (specified by its gfxFontEntry)
  3574      * is already in the fontgroup's list of actual fonts
  3575      */
  3576     bool HasFont(const gfxFontEntry *aFontEntry);
  3578     const nsString& GetFamilies() { return mFamilies; }
  3580     // This returns the preferred underline for this font group.
  3581     // Some CJK fonts have wrong underline offset in its metrics.
  3582     // If this group has such "bad" font, each platform's gfxFontGroup initialized mUnderlineOffset.
  3583     // The value should be lower value of first font's metrics and the bad font's metrics.
  3584     // Otherwise, this returns from first font's metrics.
  3585     enum { UNDERLINE_OFFSET_NOT_SET = INT16_MAX };
  3586     virtual gfxFloat GetUnderlineOffset() {
  3587         if (mUnderlineOffset == UNDERLINE_OFFSET_NOT_SET)
  3588             mUnderlineOffset = GetFontAt(0)->GetMetrics().underlineOffset;
  3589         return mUnderlineOffset;
  3592     virtual already_AddRefed<gfxFont>
  3593         FindFontForChar(uint32_t ch, uint32_t prevCh, int32_t aRunScript,
  3594                         gfxFont *aPrevMatchedFont,
  3595                         uint8_t *aMatchType);
  3597     // search through pref fonts for a character, return nullptr if no matching pref font
  3598     virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
  3600     virtual already_AddRefed<gfxFont>
  3601         WhichSystemFontSupportsChar(uint32_t aCh, int32_t aRunScript);
  3603     template<typename T>
  3604     void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
  3605                        const T *aString, uint32_t aLength,
  3606                        int32_t aRunScript);
  3608     gfxUserFontSet* GetUserFontSet();
  3610     // With downloadable fonts, the composition of the font group can change as fonts are downloaded
  3611     // for each change in state of the user font set, the generation value is bumped to avoid picking up
  3612     // previously created text runs in the text run word cache.  For font groups based on stylesheets
  3613     // with no @font-face rule, this always returns 0.
  3614     uint64_t GetGeneration();
  3616     // used when logging text performance
  3617     gfxTextPerfMetrics *GetTextPerfMetrics() { return mTextPerf; }
  3618     void SetTextPerfMetrics(gfxTextPerfMetrics *aTextPerf) { mTextPerf = aTextPerf; }
  3620     // This will call UpdateFontList() if the user font set is changed.
  3621     void SetUserFontSet(gfxUserFontSet *aUserFontSet);
  3623     // If there is a user font set, check to see whether the font list or any
  3624     // caches need updating.
  3625     virtual void UpdateFontList();
  3627     bool ShouldSkipDrawing() const {
  3628         return mSkipDrawing;
  3631     class LazyReferenceContextGetter {
  3632     public:
  3633       virtual already_AddRefed<gfxContext> GetRefContext() = 0;
  3634     };
  3635     // The gfxFontGroup keeps ownership of this textrun.
  3636     // It is only guaranteed to exist until the next call to GetEllipsisTextRun
  3637     // (which might use a different appUnitsPerDev value) for the font group,
  3638     // or until UpdateFontList is called, or the fontgroup is destroyed.
  3639     // Get it/use it/forget it :) - don't keep a reference that might go stale.
  3640     gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel,
  3641                                    LazyReferenceContextGetter& aRefContextGetter);
  3643 protected:
  3644     nsString mFamilies;
  3645     gfxFontStyle mStyle;
  3646     nsTArray<FamilyFace> mFonts;
  3647     gfxFloat mUnderlineOffset;
  3648     gfxFloat mHyphenWidth;
  3650     nsRefPtr<gfxUserFontSet> mUserFontSet;
  3651     uint64_t mCurrGeneration;  // track the current user font set generation, rebuild font list if needed
  3653     gfxTextPerfMetrics *mTextPerf;
  3655     // Cache a textrun representing an ellipsis (useful for CSS text-overflow)
  3656     // at a specific appUnitsPerDevPixel size
  3657     nsAutoPtr<gfxTextRun>   mCachedEllipsisTextRun;
  3659     // cache the most recent pref font to avoid general pref font lookup
  3660     nsRefPtr<gfxFontFamily> mLastPrefFamily;
  3661     nsRefPtr<gfxFont>       mLastPrefFont;
  3662     eFontPrefLang           mLastPrefLang;       // lang group for last pref font
  3663     eFontPrefLang           mPageLang;
  3664     bool                    mLastPrefFirstFont;  // is this the first font in the list of pref fonts for this lang group?
  3666     bool                    mSkipDrawing; // hide text while waiting for a font
  3667                                           // download to complete (or fallback
  3668                                           // timer to fire)
  3670     /**
  3671      * Textrun creation short-cuts for special cases where we don't need to
  3672      * call a font shaper to generate glyphs.
  3673      */
  3674     gfxTextRun *MakeEmptyTextRun(const Parameters *aParams, uint32_t aFlags);
  3675     gfxTextRun *MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags);
  3676     gfxTextRun *MakeBlankTextRun(uint32_t aLength,
  3677                                  const Parameters *aParams, uint32_t aFlags);
  3679     // Initialize the list of fonts
  3680     void BuildFontList();
  3682     // Init this font group's font metrics. If there no bad fonts, you don't need to call this.
  3683     // But if there are one or more bad fonts which have bad underline offset,
  3684     // you should call this with the *first* bad font.
  3685     void InitMetricsForBadFont(gfxFont* aBadFont);
  3687     // Set up the textrun glyphs for an entire text run:
  3688     // find script runs, and then call InitScriptRun for each
  3689     template<typename T>
  3690     void InitTextRun(gfxContext *aContext,
  3691                      gfxTextRun *aTextRun,
  3692                      const T *aString,
  3693                      uint32_t aLength);
  3695     // InitTextRun helper to handle a single script run, by finding font ranges
  3696     // and calling each font's InitTextRun() as appropriate
  3697     template<typename T>
  3698     void InitScriptRun(gfxContext *aContext,
  3699                        gfxTextRun *aTextRun,
  3700                        const T *aString,
  3701                        uint32_t aScriptRunStart,
  3702                        uint32_t aScriptRunEnd,
  3703                        int32_t aRunScript);
  3705     /* If aResolveGeneric is true, then CSS/Gecko generic family names are
  3706      * replaced with preferred fonts.
  3708      * If aResolveFontName is true then fc() is called only for existing fonts
  3709      * and with actual font names.  If false then fc() is called with each
  3710      * family name in aFamilies (after resolving CSS/Gecko generic family names
  3711      * if aResolveGeneric).
  3712      * If aUseFontSet is true, the fontgroup's user font set is checked;
  3713      * if false then it is skipped.
  3714      */
  3715     bool ForEachFontInternal(const nsAString& aFamilies,
  3716                                nsIAtom *aLanguage,
  3717                                bool aResolveGeneric,
  3718                                bool aResolveFontName,
  3719                                bool aUseFontSet,
  3720                                FontCreationCallback fc,
  3721                                void *closure);
  3723     // Helper for font-matching:
  3724     // see if aCh is supported in any of the faces from aFamily;
  3725     // if so return the best style match, else return null.
  3726     already_AddRefed<gfxFont> TryAllFamilyMembers(gfxFontFamily* aFamily,
  3727                                                   uint32_t aCh);
  3729     static bool FontResolverProc(const nsAString& aName, void *aClosure);
  3731     static bool FindPlatformFont(const nsAString& aName,
  3732                                    const nsACString& aGenericName,
  3733                                    bool aUseFontSet,
  3734                                    void *closure);
  3736     static NS_HIDDEN_(nsILanguageAtomService*) gLangService;
  3737 };
  3738 #endif

mercurial