LCOV - code coverage report
Current view: top level - gfx/thebes - gfxTextRun.h (source / functions) Hit Total Coverage
Test: output.info Lines: 111 221 50.2 %
Date: 2017-07-14 16:53:18 Functions: 45 78 57.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=4 et sw=4 tw=80:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef GFX_TEXTRUN_H
       8             : #define GFX_TEXTRUN_H
       9             : 
      10             : #include <stdint.h>
      11             : 
      12             : #include "gfxTypes.h"
      13             : #include "gfxPoint.h"
      14             : #include "gfxFont.h"
      15             : #include "gfxFontConstants.h"
      16             : #include "gfxSkipChars.h"
      17             : #include "gfxPlatform.h"
      18             : #include "mozilla/MemoryReporting.h"
      19             : #include "mozilla/RefPtr.h"
      20             : #include "nsPoint.h"
      21             : #include "nsString.h"
      22             : #include "nsTArray.h"
      23             : #include "nsTextFrameUtils.h"
      24             : #include "DrawMode.h"
      25             : #include "harfbuzz/hb.h"
      26             : #include "nsUnicodeScriptCodes.h"
      27             : #include "nsColor.h"
      28             : #include "X11UndefineNone.h"
      29             : 
      30             : #ifdef DEBUG
      31             : #include <stdio.h>
      32             : #endif
      33             : 
      34             : class gfxContext;
      35             : class gfxFontGroup;
      36             : class gfxUserFontEntry;
      37             : class gfxUserFontSet;
      38             : class nsIAtom;
      39             : class nsLanguageAtomService;
      40             : class gfxMissingFontRecorder;
      41             : 
      42             : namespace mozilla {
      43             : class SVGContextPaint;
      44             : enum class StyleHyphens : uint8_t;
      45             : };
      46             : 
      47             : /**
      48             :  * Callback for Draw() to use when drawing text with mode
      49             :  * DrawMode::GLYPH_PATH.
      50             :  */
      51             : struct gfxTextRunDrawCallbacks {
      52             : 
      53             :     /**
      54             :      * Constructs a new DrawCallbacks object.
      55             :      *
      56             :      * @param aShouldPaintSVGGlyphs If true, SVG glyphs will be painted.  If
      57             :      *   false, SVG glyphs will not be painted; fallback plain glyphs are not
      58             :      *   emitted either.
      59             :      */
      60           0 :     explicit gfxTextRunDrawCallbacks(bool aShouldPaintSVGGlyphs = false)
      61           0 :       : mShouldPaintSVGGlyphs(aShouldPaintSVGGlyphs)
      62             :     {
      63           0 :     }
      64             : 
      65             :     /**
      66             :      * Called when a path has been emitted to the gfxContext when
      67             :      * painting a text run.  This can be called any number of times,
      68             :      * due to partial ligatures and intervening SVG glyphs.
      69             :      */
      70             :     virtual void NotifyGlyphPathEmitted() = 0;
      71             : 
      72             :     bool mShouldPaintSVGGlyphs;
      73             : };
      74             : 
      75             : /**
      76             :  * gfxTextRun is an abstraction for drawing and measuring substrings of a run
      77             :  * of text. It stores runs of positioned glyph data, each run having a single
      78             :  * gfxFont. The glyphs are associated with a string of source text, and the
      79             :  * gfxTextRun APIs take parameters that are offsets into that source text.
      80             :  *
      81             :  * gfxTextRuns are mostly immutable. The only things that can change are
      82             :  * inter-cluster spacing and line break placement. Spacing is always obtained
      83             :  * lazily by methods that need it, it is not cached. Line breaks are stored
      84             :  * persistently (insofar as they affect the shaping of glyphs; gfxTextRun does
      85             :  * not actually do anything to explicitly account for line breaks). Initially
      86             :  * there are no line breaks. The textrun can record line breaks before or after
      87             :  * any given cluster. (Line breaks specified inside clusters are ignored.)
      88             :  *
      89             :  * It is important that zero-length substrings are handled correctly. This will
      90             :  * be on the test!
      91             :  */
      92             : class gfxTextRun : public gfxShapedText
      93             : {
      94         418 :     NS_INLINE_DECL_REFCOUNTING(gfxTextRun);
      95             : 
      96             : protected:
      97             :     // Override operator delete to properly free the object that was
      98             :     // allocated via malloc.
      99          71 :     void operator delete(void* p) {
     100          71 :         free(p);
     101          71 :     }
     102             : 
     103             :     virtual ~gfxTextRun();
     104             : 
     105             : public:
     106             :     typedef gfxFont::RunMetrics Metrics;
     107             :     typedef mozilla::gfx::DrawTarget DrawTarget;
     108             : 
     109             :     // Public textrun API for general use
     110             : 
     111           2 :     bool IsClusterStart(uint32_t aPos) const {
     112           2 :         MOZ_ASSERT(aPos < GetLength());
     113           2 :         return mCharacterGlyphs[aPos].IsClusterStart();
     114             :     }
     115           0 :     bool IsLigatureGroupStart(uint32_t aPos) const {
     116           0 :         MOZ_ASSERT(aPos < GetLength());
     117           0 :         return mCharacterGlyphs[aPos].IsLigatureGroupStart();
     118             :     }
     119         164 :     bool CanBreakLineBefore(uint32_t aPos) const {
     120         164 :         return CanBreakBefore(aPos) == CompressedGlyph::FLAG_BREAK_TYPE_NORMAL;
     121             :     }
     122           0 :     bool CanHyphenateBefore(uint32_t aPos) const {
     123           0 :         return CanBreakBefore(aPos) == CompressedGlyph::FLAG_BREAK_TYPE_HYPHEN;
     124             :     }
     125             : 
     126             :     // Returns a gfxShapedText::CompressedGlyph::FLAG_BREAK_TYPE_* value
     127             :     // as defined in gfxFont.h (may be NONE, NORMAL or HYPHEN).
     128         164 :     uint8_t CanBreakBefore(uint32_t aPos) const {
     129         164 :         MOZ_ASSERT(aPos < GetLength());
     130         164 :         return mCharacterGlyphs[aPos].CanBreakBefore();
     131             :     }
     132             : 
     133             :     bool CharIsSpace(uint32_t aPos) const {
     134             :         MOZ_ASSERT(aPos < GetLength());
     135             :         return mCharacterGlyphs[aPos].CharIsSpace();
     136             :     }
     137         208 :     bool CharIsTab(uint32_t aPos) const {
     138         208 :         MOZ_ASSERT(aPos < GetLength());
     139         208 :         return mCharacterGlyphs[aPos].CharIsTab();
     140             :     }
     141         208 :     bool CharIsNewline(uint32_t aPos) const {
     142         208 :         MOZ_ASSERT(aPos < GetLength());
     143         208 :         return mCharacterGlyphs[aPos].CharIsNewline();
     144             :     }
     145           0 :     bool CharMayHaveEmphasisMark(uint32_t aPos) const {
     146           0 :         MOZ_ASSERT(aPos < GetLength());
     147           0 :         return mCharacterGlyphs[aPos].CharMayHaveEmphasisMark();
     148             :     }
     149             : 
     150             :     // All offsets are in terms of the string passed into MakeTextRun.
     151             : 
     152             :     // Describe range [start, end) of a text run. The range is
     153             :     // restricted to grapheme cluster boundaries.
     154             :     struct Range
     155             :     {
     156             :         uint32_t start;
     157             :         uint32_t end;
     158         122 :         uint32_t Length() const { return end - start; }
     159             : 
     160          19 :         Range() : start(0), end(0) {}
     161         980 :         Range(uint32_t aStart, uint32_t aEnd)
     162         980 :             : start(aStart), end(aEnd) {}
     163           0 :         explicit Range(const gfxTextRun* aTextRun)
     164           0 :             : start(0), end(aTextRun->GetLength()) {}
     165             :     };
     166             : 
     167             :     // All coordinates are in layout/app units
     168             : 
     169             :     /**
     170             :      * Set the potential linebreaks for a substring of the textrun. These are
     171             :      * the "allow break before" points. Initially, there are no potential
     172             :      * linebreaks.
     173             :      *
     174             :      * This can change glyphs and/or geometry! Some textruns' shapes
     175             :      * depend on potential line breaks (e.g., title-case-converting textruns).
     176             :      * This function is virtual so that those textruns can reshape themselves.
     177             :      *
     178             :      * @return true if this changed the linebreaks, false if the new line
     179             :      * breaks are the same as the old
     180             :      */
     181             :     virtual bool SetPotentialLineBreaks(Range aRange,
     182             :                                         const uint8_t* aBreakBefore);
     183             : 
     184             :     enum class HyphenType : uint8_t {
     185             :       None,
     186             :       Explicit,
     187             :       Soft,
     188             :       AutoWithManualInSameWord,
     189             :       AutoWithoutManualInSameWord
     190             :     };
     191             : 
     192             :     struct HyphenationState {
     193             :       uint32_t mostRecentBoundary = 0;
     194             :       bool     hasManualHyphen = false;
     195             :       bool     hasExplicitHyphen = false;
     196             :       bool     hasAutoHyphen = false;
     197             :     };
     198             : 
     199             :     /**
     200             :      * Layout provides PropertyProvider objects. These allow detection of
     201             :      * potential line break points and computation of spacing. We pass the data
     202             :      * this way to allow lazy data acquisition; for example BreakAndMeasureText
     203             :      * will want to only ask for properties of text it's actually looking at.
     204             :      *
     205             :      * NOTE that requested spacing may not actually be applied, if the textrun
     206             :      * is unable to apply it in some context. Exception: spacing around a
     207             :      * whitespace character MUST always be applied.
     208             :      */
     209          80 :     class PropertyProvider {
     210             :     public:
     211             :         // Detect hyphenation break opportunities in the given range; breaks
     212             :         // not at cluster boundaries will be ignored.
     213             :         virtual void GetHyphenationBreaks(Range aRange,
     214             :                                           HyphenType *aBreakBefore) const = 0;
     215             : 
     216             :         // Returns the provider's hyphenation setting, so callers can decide
     217             :         // whether it is necessary to call GetHyphenationBreaks.
     218             :         // Result is an StyleHyphens value.
     219             :         virtual mozilla::StyleHyphens GetHyphensOption() const = 0;
     220             : 
     221             :         // Returns the extra width that will be consumed by a hyphen. This should
     222             :         // be constant for a given textrun.
     223             :         virtual gfxFloat GetHyphenWidth() const = 0;
     224             : 
     225             :         typedef gfxFont::Spacing Spacing;
     226             : 
     227             :         /**
     228             :          * Get the spacing around the indicated characters. Spacing must be zero
     229             :          * inside clusters. In other words, if character i is not
     230             :          * CLUSTER_START, then character i-1 must have zero after-spacing and
     231             :          * character i must have zero before-spacing.
     232             :          */
     233             :         virtual void GetSpacing(Range aRange, Spacing *aSpacing) const = 0;
     234             : 
     235             :         // Returns a gfxContext that can be used to measure the hyphen glyph.
     236             :         // Only called if the hyphen width is requested.
     237             :         virtual already_AddRefed<DrawTarget> GetDrawTarget() const = 0;
     238             : 
     239             :         // Return the appUnitsPerDevUnit value to be used when measuring.
     240             :         // Only called if the hyphen width is requested.
     241             :         virtual uint32_t GetAppUnitsPerDevUnit() const = 0;
     242             :     };
     243             : 
     244             :     struct DrawParams
     245             :     {
     246             :         gfxContext* context;
     247             :         DrawMode drawMode = DrawMode::GLYPH_FILL;
     248             :         nscolor textStrokeColor = 0;
     249             :         gfxPattern* textStrokePattern = nullptr;
     250             :         const mozilla::gfx::StrokeOptions *strokeOpts = nullptr;
     251             :         const mozilla::gfx::DrawOptions *drawOpts = nullptr;
     252             :         PropertyProvider* provider = nullptr;
     253             :         // If non-null, the advance width of the substring is set.
     254             :         gfxFloat* advanceWidth = nullptr;
     255             :         mozilla::SVGContextPaint* contextPaint = nullptr;
     256             :         gfxTextRunDrawCallbacks* callbacks = nullptr;
     257          21 :         explicit DrawParams(gfxContext* aContext) : context(aContext) {}
     258             :     };
     259             : 
     260             :     /**
     261             :      * Draws a substring. Uses only GetSpacing from aBreakProvider.
     262             :      * The provided point is the baseline origin on the left of the string
     263             :      * for LTR, on the right of the string for RTL.
     264             :      *
     265             :      * Drawing should respect advance widths in the sense that for LTR runs,
     266             :      *   Draw(Range(start, middle), pt, ...) followed by
     267             :      *   Draw(Range(middle, end), gfxPoint(pt.x + advance, pt.y), ...)
     268             :      * should have the same effect as
     269             :      *   Draw(Range(start, end), pt, ...)
     270             :      *
     271             :      * For RTL runs the rule is:
     272             :      *   Draw(Range(middle, end), pt, ...) followed by
     273             :      *   Draw(Range(start, middle), gfxPoint(pt.x + advance, pt.y), ...)
     274             :      * should have the same effect as
     275             :      *   Draw(Range(start, end), pt, ...)
     276             :      *
     277             :      * Glyphs should be drawn in logical content order, which can be significant
     278             :      * if they overlap (perhaps due to negative spacing).
     279             :      */
     280             :     void Draw(Range aRange, gfxPoint aPt, const DrawParams& aParams) const;
     281             : 
     282             :     /**
     283             :      * Draws the emphasis marks for this text run. Uses only GetSpacing
     284             :      * from aProvider. The provided point is the baseline origin of the
     285             :      * line of emphasis marks.
     286             :      */
     287             :     void DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark,
     288             :                            gfxFloat aMarkAdvance, gfxPoint aPt,
     289             :                            Range aRange, PropertyProvider* aProvider) const;
     290             : 
     291             :     /**
     292             :      * Computes the ReflowMetrics for a substring.
     293             :      * Uses GetSpacing from aBreakProvider.
     294             :      * @param aBoundingBoxType which kind of bounding box (loose/tight)
     295             :      */
     296             :     Metrics MeasureText(Range aRange,
     297             :                         gfxFont::BoundingBoxType aBoundingBoxType,
     298             :                         DrawTarget* aDrawTargetForTightBoundingBox,
     299             :                         PropertyProvider* aProvider) const;
     300             : 
     301           0 :     Metrics MeasureText(gfxFont::BoundingBoxType aBoundingBoxType,
     302             :                         DrawTarget* aDrawTargetForTightBoundingBox,
     303             :                         PropertyProvider* aProvider = nullptr) const {
     304             :         return MeasureText(Range(this), aBoundingBoxType,
     305           0 :                            aDrawTargetForTightBoundingBox, aProvider);
     306             :     }
     307             : 
     308             :     /**
     309             :      * Computes just the advance width for a substring.
     310             :      * Uses GetSpacing from aBreakProvider.
     311             :      * If aSpacing is not null, the spacing attached before and after
     312             :      * the substring would be returned in it. NOTE: the spacing is
     313             :      * included in the advance width.
     314             :      */
     315             :     gfxFloat GetAdvanceWidth(Range aRange, PropertyProvider *aProvider,
     316             :                              PropertyProvider::Spacing*
     317             :                                  aSpacing = nullptr) const;
     318             : 
     319           0 :     gfxFloat GetAdvanceWidth() const {
     320           0 :         return GetAdvanceWidth(Range(this), nullptr);
     321             :     }
     322             : 
     323             :     /**
     324             :      * Clear all stored line breaks for the given range (both before and after),
     325             :      * and then set the line-break state before aRange.start to aBreakBefore and
     326             :      * after the last cluster to aBreakAfter.
     327             :      *
     328             :      * We require that before and after line breaks be consistent. For clusters
     329             :      * i and i+1, we require that if there is a break after cluster i, a break
     330             :      * will be specified before cluster i+1. This may be temporarily violated
     331             :      * (e.g. after reflowing line L and before reflowing line L+1); to handle
     332             :      * these temporary violations, we say that there is a break betwen i and i+1
     333             :      * if a break is specified after i OR a break is specified before i+1.
     334             :      *
     335             :      * This can change textrun geometry! The existence of a linebreak can affect
     336             :      * the advance width of the cluster before the break (when kerning) or the
     337             :      * geometry of one cluster before the break or any number of clusters
     338             :      * after the break. (The one-cluster-before-the-break limit is somewhat
     339             :      * arbitrary; if some scripts require breaking it, then we need to
     340             :      * alter nsTextFrame::TrimTrailingWhitespace, perhaps drastically becase
     341             :      * it could affect the layout of frames before it...)
     342             :      *
     343             :      * We return true if glyphs or geometry changed, false otherwise. This
     344             :      * function is virtual so that gfxTextRun subclasses can reshape
     345             :      * properly.
     346             :      *
     347             :      * @param aAdvanceWidthDelta if non-null, returns the change in advance
     348             :      * width of the given range.
     349             :      */
     350             :     virtual bool SetLineBreaks(Range aRange,
     351             :                                bool aLineBreakBefore, bool aLineBreakAfter,
     352             :                                gfxFloat* aAdvanceWidthDelta);
     353             : 
     354             :     enum SuppressBreak {
     355             :       eNoSuppressBreak,
     356             :       // Measure the range of text as if there is no break before it.
     357             :       eSuppressInitialBreak,
     358             :       // Measure the range of text as if it contains no break
     359             :       eSuppressAllBreaks
     360             :     };
     361             : 
     362             :     void ClassifyAutoHyphenations(uint32_t aStart, Range aRange,
     363             :                                   nsTArray<HyphenType>& aHyphenBuffer,
     364             :                                   HyphenationState* aWordState);
     365             : 
     366             :     /**
     367             :      * Finds the longest substring that will fit into the given width.
     368             :      * Uses GetHyphenationBreaks and GetSpacing from aBreakProvider.
     369             :      * Guarantees the following:
     370             :      * -- 0 <= result <= aMaxLength
     371             :      * -- result is the maximal value of N such that either
     372             :      *       N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
     373             :      *   OR  N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
     374             :      *   OR  N == aMaxLength && GetAdvanceWidth(aStart, N) <= aWidth
     375             :      * where GetAdvanceWidth assumes the effect of
     376             :      * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
     377             :      * -- if no such N exists, then result is the smallest N such that
     378             :      *       N < aMaxLength && line break at N
     379             :      *   OR  N < aMaxLength && hyphen break at N
     380             :      *   OR  N == aMaxLength
     381             :      *
     382             :      * The call has the effect of
     383             :      * SetLineBreaks(aStart, result, aLineBreakBefore, result < aMaxLength, aProvider)
     384             :      * and the returned metrics and the invariants above reflect this.
     385             :      *
     386             :      * @param aMaxLength this can be UINT32_MAX, in which case the length used
     387             :      * is up to the end of the string
     388             :      * @param aLineBreakBefore set to true if and only if there is an actual
     389             :      * line break at the start of this string.
     390             :      * @param aSuppressBreak what break should be suppressed.
     391             :      * @param aTrimWhitespace if non-null, then we allow a trailing run of
     392             :      * spaces to be trimmed; the width of the space(s) will not be included in
     393             :      * the measured string width for comparison with the limit aWidth, and
     394             :      * trimmed spaces will not be included in returned metrics. The width
     395             :      * of the trimmed spaces will be returned in aTrimWhitespace.
     396             :      * Trimmed spaces are still counted in the "characters fit" result.
     397             :      * @param aMetrics if non-null, we fill this in for the returned substring.
     398             :      * If a hyphenation break was used, the hyphen is NOT included in the returned metrics.
     399             :      * @param aBoundingBoxType whether to make the bounding box in aMetrics tight
     400             :      * @param aDrawTargetForTightBoundingbox a reference DrawTarget to get the
     401             :      * tight bounding box, if requested
     402             :      * @param aUsedHyphenation if non-null, records if we selected a hyphenation break
     403             :      * @param aLastBreak if non-null and result is aMaxLength, we set this to
     404             :      * the maximal N such that
     405             :      *       N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
     406             :      *   OR  N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
     407             :      * or UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
     408             :      * the effect of
     409             :      * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
     410             :      *
     411             :      * @param aCanWordWrap true if we can break between any two grapheme
     412             :      * clusters. This is set by overflow-wrap|word-wrap: break-word
     413             :      *
     414             :      * @param aBreakPriority in/out the priority of the break opportunity
     415             :      * saved in the line. If we are prioritizing break opportunities, we will
     416             :      * not set a break with a lower priority. @see gfxBreakPriority.
     417             :      *
     418             :      * Note that negative advance widths are possible especially if negative
     419             :      * spacing is provided.
     420             :      */
     421             :     uint32_t BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
     422             :                                  bool aLineBreakBefore, gfxFloat aWidth,
     423             :                                  PropertyProvider *aProvider,
     424             :                                  SuppressBreak aSuppressBreak,
     425             :                                  gfxFloat *aTrimWhitespace,
     426             :                                  bool aHangWhitespace,
     427             :                                  Metrics *aMetrics,
     428             :                                  gfxFont::BoundingBoxType aBoundingBoxType,
     429             :                                  DrawTarget* aDrawTargetForTightBoundingBox,
     430             :                                  bool *aUsedHyphenation,
     431             :                                  uint32_t *aLastBreak,
     432             :                                  bool aCanWordWrap,
     433             :                                  gfxBreakPriority *aBreakPriority);
     434             : 
     435             :     // Utility getters
     436             : 
     437          48 :     void *GetUserData() const { return mUserData; }
     438           9 :     void SetUserData(void *aUserData) { mUserData = aUserData; }
     439             : 
     440           0 :     void SetFlagBits(nsTextFrameUtils::Flags aFlags) {
     441           0 :       mFlags2 |= aFlags;
     442           0 :     }
     443          10 :     void ClearFlagBits(nsTextFrameUtils::Flags aFlags) {
     444          10 :       mFlags2 &= ~aFlags;
     445          10 :     }
     446         125 :     const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
     447          71 :     gfxFontGroup *GetFontGroup() const { return mFontGroup; }
     448             : 
     449             : 
     450             :     // Call this, don't call "new gfxTextRun" directly. This does custom
     451             :     // allocation and initialization
     452             :     static already_AddRefed<gfxTextRun>
     453             :     Create(const gfxTextRunFactory::Parameters *aParams,
     454             :            uint32_t aLength, gfxFontGroup *aFontGroup,
     455             :            mozilla::gfx::ShapedTextFlags aFlags,
     456             :            nsTextFrameUtils::Flags aFlags2);
     457             : 
     458             :     // The text is divided into GlyphRuns as necessary. (In the vast majority
     459             :     // of cases, a gfxTextRun contains just a single GlyphRun.)
     460          83 :     struct GlyphRun {
     461             :         RefPtr<gfxFont> mFont; // never null in a valid GlyphRun
     462             :         uint32_t        mCharacterOffset; // into original UTF16 string
     463             :         mozilla::gfx::ShapedTextFlags mOrientation; // gfxTextRunFactory::TEXT_ORIENT_* value
     464             :         uint8_t         mMatchType;
     465             :     };
     466             : 
     467             :     class GlyphRunIterator {
     468             :     public:
     469          77 :         GlyphRunIterator(const gfxTextRun *aTextRun, Range aRange)
     470          77 :           : mTextRun(aTextRun)
     471          77 :           , mStartOffset(aRange.start)
     472         154 :           , mEndOffset(aRange.end) {
     473          77 :             mNextIndex = mTextRun->FindFirstGlyphRunContaining(aRange.start);
     474          77 :         }
     475             :         bool NextRun();
     476         284 :         const GlyphRun *GetGlyphRun() const { return mGlyphRun; }
     477          69 :         uint32_t GetStringStart() const { return mStringStart; }
     478          69 :         uint32_t GetStringEnd() const { return mStringEnd; }
     479             :     private:
     480             :         const gfxTextRun *mTextRun;
     481             :         MOZ_INIT_OUTSIDE_CTOR const GlyphRun   *mGlyphRun;
     482             :         MOZ_INIT_OUTSIDE_CTOR uint32_t    mStringStart;
     483             :         MOZ_INIT_OUTSIDE_CTOR uint32_t    mStringEnd;
     484             :         uint32_t    mNextIndex;
     485             :         uint32_t    mStartOffset;
     486             :         uint32_t    mEndOffset;
     487             :     };
     488             : 
     489             :     class GlyphRunOffsetComparator {
     490             :     public:
     491           0 :         bool Equals(const GlyphRun& a,
     492             :                       const GlyphRun& b) const
     493             :         {
     494           0 :             return a.mCharacterOffset == b.mCharacterOffset;
     495             :         }
     496             : 
     497           0 :         bool LessThan(const GlyphRun& a,
     498             :                         const GlyphRun& b) const
     499             :         {
     500           0 :             return a.mCharacterOffset < b.mCharacterOffset;
     501             :         }
     502             :     };
     503             : 
     504             :     friend class GlyphRunIterator;
     505             :     friend class FontSelector;
     506             : 
     507             :     // API for setting up the textrun glyphs. Should only be called by
     508             :     // things that construct textruns.
     509             :     /**
     510             :      * We've found a run of text that should use a particular font. Call this
     511             :      * only during initialization when font substitution has been computed.
     512             :      * Call it before setting up the glyphs for the characters in this run;
     513             :      * SetMissingGlyph requires that the correct glyphrun be installed.
     514             :      *
     515             :      * If aForceNewRun, a new glyph run will be added, even if the
     516             :      * previously added run uses the same font.  If glyph runs are
     517             :      * added out of strictly increasing aStartCharIndex order (via
     518             :      * force), then SortGlyphRuns must be called after all glyph runs
     519             :      * are added before any further operations are performed with this
     520             :      * TextRun.
     521             :      */
     522             :     nsresult AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
     523             :                          uint32_t aStartCharIndex, bool aForceNewRun,
     524             :                          mozilla::gfx::ShapedTextFlags aOrientation);
     525           0 :     void ResetGlyphRuns()
     526             :     {
     527           0 :         if (mHasGlyphRunArray) {
     528           0 :             MOZ_ASSERT(mGlyphRunArray.Length() > 1);
     529             :             // Discard all but the first GlyphRun...
     530           0 :             mGlyphRunArray.TruncateLength(1);
     531             :             // ...and then convert to the single-run representation.
     532           0 :             ConvertFromGlyphRunArray();
     533             :         }
     534             :         // Clear out the one remaining GlyphRun.
     535           0 :         mSingleGlyphRun.mFont = nullptr;
     536           0 :     }
     537             :     void SortGlyphRuns();
     538             :     void SanitizeGlyphRuns();
     539             : 
     540          64 :     const CompressedGlyph* GetCharacterGlyphs() const final {
     541          64 :         MOZ_ASSERT(mCharacterGlyphs, "failed to initialize mCharacterGlyphs");
     542          64 :         return mCharacterGlyphs;
     543             :     }
     544         251 :     CompressedGlyph* GetCharacterGlyphs() final {
     545         251 :         MOZ_ASSERT(mCharacterGlyphs, "failed to initialize mCharacterGlyphs");
     546         251 :         return mCharacterGlyphs;
     547             :     }
     548             : 
     549             :     // clean out results from shaping in progress, used for fallback scenarios
     550             :     void ClearGlyphsAndCharacters();
     551             : 
     552             :     void SetSpaceGlyph(gfxFont* aFont, DrawTarget* aDrawTarget,
     553             :                        uint32_t aCharIndex,
     554             :                        mozilla::gfx::ShapedTextFlags aOrientation);
     555             : 
     556             :     // Set the glyph data for the given character index to the font's
     557             :     // space glyph, IF this can be done as a "simple" glyph record
     558             :     // (not requiring a DetailedGlyph entry). This avoids the need to call
     559             :     // the font shaper and go through the shaped-word cache for most spaces.
     560             :     //
     561             :     // The parameter aSpaceChar is the original character code for which
     562             :     // this space glyph is being used; if this is U+0020, we need to record
     563             :     // that it could be trimmed at a run edge, whereas other kinds of space
     564             :     // (currently just U+00A0) would not be trimmable/breakable.
     565             :     //
     566             :     // Returns true if it was able to set simple glyph data for the space;
     567             :     // if it returns false, the caller needs to fall back to some other
     568             :     // means to create the necessary (detailed) glyph data.
     569             :     bool SetSpaceGlyphIfSimple(gfxFont *aFont, uint32_t aCharIndex,
     570             :                                char16_t aSpaceChar, 
     571             :                                mozilla::gfx::ShapedTextFlags aOrientation);
     572             : 
     573             :     // Record the positions of specific characters that layout may need to
     574             :     // detect in the textrun, even though it doesn't have an explicit copy
     575             :     // of the original text. These are recorded using flag bits in the
     576             :     // CompressedGlyph record; if necessary, we convert "simple" glyph records
     577             :     // to "complex" ones as the Tab and Newline flags are not present in
     578             :     // simple CompressedGlyph records.
     579           0 :     void SetIsTab(uint32_t aIndex) {
     580           0 :         EnsureComplexGlyph(aIndex).SetIsTab();
     581           0 :     }
     582           0 :     void SetIsNewline(uint32_t aIndex) {
     583           0 :         EnsureComplexGlyph(aIndex).SetIsNewline();
     584           0 :     }
     585           0 :     void SetNoEmphasisMark(uint32_t aIndex) {
     586           0 :         EnsureComplexGlyph(aIndex).SetNoEmphasisMark();
     587           0 :     }
     588             : 
     589             :     /**
     590             :      * Prefetch all the glyph extents needed to ensure that Measure calls
     591             :      * on this textrun not requesting tight boundingBoxes will succeed. Note
     592             :      * that some glyph extents might not be fetched due to OOM or other
     593             :      * errors.
     594             :      */
     595             :     void FetchGlyphExtents(DrawTarget* aRefDrawTarget);
     596             : 
     597             :     uint32_t CountMissingGlyphs() const;
     598             : 
     599          92 :     const GlyphRun* GetGlyphRuns(uint32_t* aNumGlyphRuns) const
     600             :     {
     601          92 :         if (mHasGlyphRunArray) {
     602           0 :             *aNumGlyphRuns = mGlyphRunArray.Length();
     603           0 :             return mGlyphRunArray.Elements();
     604             :         } else {
     605          92 :             *aNumGlyphRuns = mSingleGlyphRun.mFont ? 1 : 0;
     606          92 :             return &mSingleGlyphRun;
     607             :         }
     608             :     }
     609             :     // Returns the index of the GlyphRun containing the given offset.
     610             :     // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
     611             :     uint32_t FindFirstGlyphRunContaining(uint32_t aOffset) const;
     612             : 
     613             :     // Copy glyph data from a ShapedWord into this textrun.
     614             :     void CopyGlyphDataFrom(gfxShapedWord *aSource, uint32_t aStart);
     615             : 
     616             :     // Copy glyph data for a range of characters from aSource to this
     617             :     // textrun.
     618             :     void CopyGlyphDataFrom(gfxTextRun *aSource, Range aRange, uint32_t aDest);
     619             : 
     620             :     // Tell the textrun to release its reference to its creating gfxFontGroup
     621             :     // immediately, rather than on destruction. This is used for textruns
     622             :     // that are actually owned by a gfxFontGroup, so that they don't keep it
     623             :     // permanently alive due to a circular reference. (The caller of this is
     624             :     // taking responsibility for ensuring the textrun will not outlive its
     625             :     // mFontGroup.)
     626             :     void ReleaseFontGroup();
     627             : 
     628           0 :     struct LigatureData {
     629             :         // textrun range of the containing ligature
     630             :         Range mRange;
     631             :         // appunits advance to the start of the ligature part within the ligature;
     632             :         // never includes any spacing
     633             :         gfxFloat mPartAdvance;
     634             :         // appunits width of the ligature part; includes before-spacing
     635             :         // when the part is at the start of the ligature, and after-spacing
     636             :         // when the part is as the end of the ligature
     637             :         gfxFloat mPartWidth;
     638             : 
     639             :         bool mClipBeforePart;
     640             :         bool mClipAfterPart;
     641             :     };
     642             : 
     643             :     // return storage used by this run, for memory reporter;
     644             :     // nsTransformedTextRun needs to override this as it holds additional data
     645             :     virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     646             :       MOZ_MUST_OVERRIDE;
     647             :     virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     648             :       MOZ_MUST_OVERRIDE;
     649             : 
     650         324 :     nsTextFrameUtils::Flags GetFlags2() const {
     651         324 :         return mFlags2;
     652             :     }
     653             : 
     654             :     // Get the size, if it hasn't already been gotten, marking as it goes.
     655           0 :     size_t MaybeSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)  {
     656           0 :         if (mFlags2 & nsTextFrameUtils::Flags::TEXT_RUN_SIZE_ACCOUNTED) {
     657           0 :             return 0;
     658             :         }
     659           0 :         mFlags2 |= nsTextFrameUtils::Flags::TEXT_RUN_SIZE_ACCOUNTED;
     660           0 :         return SizeOfIncludingThis(aMallocSizeOf);
     661             :     }
     662           0 :     void ResetSizeOfAccountingFlags() {
     663          81 :         mFlags2 &= ~nsTextFrameUtils::Flags::TEXT_RUN_SIZE_ACCOUNTED;
     664           0 :     }
     665             : 
     666             :     // shaping state - for some font features, fallback is required that
     667             :     // affects the entire run. for example, fallback for one script/font
     668             :     // portion of a textrun requires fallback to be applied to the entire run
     669             : 
     670             :     enum ShapingState : uint8_t {
     671             :         eShapingState_Normal,                 // default state
     672             :         eShapingState_ShapingWithFeature,     // have shaped with feature
     673             :         eShapingState_ShapingWithFallback,    // have shaped with fallback
     674             :         eShapingState_Aborted,                // abort initial iteration
     675             :         eShapingState_ForceFallbackFeature    // redo with fallback forced on
     676             :     };
     677             : 
     678         142 :     ShapingState GetShapingState() const { return mShapingState; }
     679           0 :     void SetShapingState(ShapingState aShapingState) {
     680           0 :         mShapingState = aShapingState;
     681           0 :     }
     682             : 
     683        1164 :     int32_t GetAdvanceForGlyph(uint32_t aIndex) const
     684             :     {
     685        1164 :         const CompressedGlyph& glyphData = mCharacterGlyphs[aIndex];
     686        1164 :         if (glyphData.IsSimpleGlyph()) {
     687        1164 :             return glyphData.GetSimpleAdvance();
     688             :         }
     689           0 :         uint32_t glyphCount = glyphData.GetGlyphCount();
     690           0 :         if (!glyphCount) {
     691           0 :             return 0;
     692             :         }
     693           0 :         const DetailedGlyph* details = GetDetailedGlyphs(aIndex);
     694           0 :         int32_t advance = 0;
     695           0 :         for (uint32_t j = 0; j < glyphCount; ++j, ++details) {
     696           0 :             advance += details->mAdvance;
     697             :         }
     698           0 :         return advance;
     699             :     }
     700             : 
     701             : #ifdef DEBUG
     702             :     void Dump(FILE* aOutput);
     703             : #endif
     704             : 
     705             : protected:
     706             :     /**
     707             :      * Create a textrun, and set its mCharacterGlyphs to point immediately
     708             :      * after the base object; this is ONLY used in conjunction with placement
     709             :      * new, after allocating a block large enough for the glyph records to
     710             :      * follow the base textrun object.
     711             :      */
     712             :     gfxTextRun(const gfxTextRunFactory::Parameters *aParams,
     713             :                uint32_t aLength, gfxFontGroup *aFontGroup,
     714             :                mozilla::gfx::ShapedTextFlags aFlags,
     715             :                nsTextFrameUtils::Flags aFlags2);
     716             : 
     717             :     /**
     718             :      * Helper for the Create() factory method to allocate the required
     719             :      * glyph storage for a textrun object with the basic size aSize,
     720             :      * plus room for aLength glyph records.
     721             :      */
     722             :     static void* AllocateStorageForTextRun(size_t aSize, uint32_t aLength);
     723             : 
     724             :     // Pointer to the array of CompressedGlyph records; must be initialized
     725             :     // when the object is constructed.
     726             :     CompressedGlyph *mCharacterGlyphs;
     727             : 
     728             : private:
     729             :     // **** general helpers ****
     730             : 
     731             :     // Get the total advance for a range of glyphs.
     732             :     int32_t GetAdvanceForGlyphs(Range aRange) const;
     733             : 
     734             :     // Spacing for characters outside the range aSpacingStart/aSpacingEnd
     735             :     // is assumed to be zero; such characters are not passed to aProvider.
     736             :     // This is useful to protect aProvider from being passed character indices
     737             :     // it is not currently able to handle.
     738             :     bool GetAdjustedSpacingArray(Range aRange, PropertyProvider *aProvider,
     739             :                                  Range aSpacingRange,
     740             :                                  nsTArray<PropertyProvider::Spacing>*
     741             :                                      aSpacing) const;
     742             : 
     743           0 :     CompressedGlyph& EnsureComplexGlyph(uint32_t aIndex)
     744             :     {
     745           0 :         gfxShapedText::EnsureComplexGlyph(aIndex, mCharacterGlyphs[aIndex]);
     746           0 :         return mCharacterGlyphs[aIndex];
     747             :     }
     748             : 
     749             :     //  **** ligature helpers ****
     750             :     // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
     751             :     // to handle requests that begin or end inside a ligature)
     752             : 
     753             :     // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
     754             :     LigatureData ComputeLigatureData(Range aPartRange,
     755             :                                      PropertyProvider *aProvider) const;
     756             :     gfxFloat ComputePartialLigatureWidth(Range aPartRange,
     757             :                                          PropertyProvider *aProvider) const;
     758             :     void DrawPartialLigature(gfxFont *aFont, Range aRange,
     759             :                              gfxPoint *aPt, PropertyProvider *aProvider,
     760             :                              TextRunDrawParams& aParams,
     761             :                              mozilla::gfx::ShapedTextFlags aOrientation) const;
     762             :     // Advance aRange.start to the start of the nearest ligature, back
     763             :     // up aRange.end to the nearest ligature end; may result in
     764             :     // aRange->start == aRange->end.
     765             :     void ShrinkToLigatureBoundaries(Range* aRange) const;
     766             :     // result in appunits
     767             :     gfxFloat GetPartialLigatureWidth(Range aRange,
     768             :                                      PropertyProvider *aProvider) const;
     769             :     void AccumulatePartialLigatureMetrics(gfxFont *aFont, Range aRange,
     770             :                                           gfxFont::BoundingBoxType aBoundingBoxType,
     771             :                                           DrawTarget* aRefDrawTarget,
     772             :                                           PropertyProvider *aProvider,
     773             :                                           mozilla::gfx::ShapedTextFlags aOrientation,
     774             :                                           Metrics *aMetrics) const;
     775             : 
     776             :     // **** measurement helper ****
     777             :     void AccumulateMetricsForRun(gfxFont *aFont, Range aRange,
     778             :                                  gfxFont::BoundingBoxType aBoundingBoxType,
     779             :                                  DrawTarget* aRefDrawTarget,
     780             :                                  PropertyProvider *aProvider,
     781             :                                  Range aSpacingRange,
     782             :                                  mozilla::gfx::ShapedTextFlags aOrientation,
     783             :                                  Metrics *aMetrics) const;
     784             : 
     785             :     // **** drawing helper ****
     786             :     void DrawGlyphs(gfxFont *aFont, Range aRange, gfxPoint *aPt,
     787             :                     PropertyProvider *aProvider, Range aSpacingRange,
     788             :                     TextRunDrawParams& aParams,
     789             :                     mozilla::gfx::ShapedTextFlags aOrientation) const;
     790             : 
     791             :     // The textrun holds either a single GlyphRun -or- an array;
     792             :     // the flag mHasGlyphRunArray tells us which is present.
     793             :     union {
     794             :         GlyphRun           mSingleGlyphRun;
     795             :         nsTArray<GlyphRun> mGlyphRunArray;
     796             :     };
     797             : 
     798           0 :     void ConvertToGlyphRunArray() {
     799           0 :         MOZ_ASSERT(!mHasGlyphRunArray && mSingleGlyphRun.mFont);
     800           0 :         GlyphRun tmp = mozilla::Move(mSingleGlyphRun);
     801           0 :         mSingleGlyphRun.~GlyphRun();
     802           0 :         new (&mGlyphRunArray) nsTArray<GlyphRun>(2);
     803           0 :         mGlyphRunArray.AppendElement(mozilla::Move(tmp));
     804           0 :         mHasGlyphRunArray = true;
     805           0 :     }
     806             : 
     807           0 :     void ConvertFromGlyphRunArray() {
     808           0 :         MOZ_ASSERT(mHasGlyphRunArray && mGlyphRunArray.Length() == 1);
     809           0 :         GlyphRun tmp = mozilla::Move(mGlyphRunArray[0]);
     810           0 :         mGlyphRunArray.~nsTArray<GlyphRun>();
     811           0 :         new (&mSingleGlyphRun) GlyphRun(mozilla::Move(tmp));
     812           0 :         mHasGlyphRunArray = false;
     813           0 :     }
     814             : 
     815             :     void             *mUserData;
     816             :     gfxFontGroup     *mFontGroup; // addrefed on creation, but our reference
     817             :                                   // may be released by ReleaseFontGroup()
     818             :     gfxSkipChars      mSkipChars;
     819             : 
     820             :     nsTextFrameUtils::Flags mFlags2; // additional flags (see also gfxShapedText::mFlags)
     821             : 
     822             :     bool              mSkipDrawing; // true if the font group we used had a user font
     823             :                                     // download that's in progress, so we should hide text
     824             :                                     // until the download completes (or timeout fires)
     825             :     bool              mReleasedFontGroup; // we already called NS_RELEASE on
     826             :                                           // mFontGroup, so don't do it again
     827             :     bool              mHasGlyphRunArray; // whether we're using an array or
     828             :                                          // just storing a single glyphrun
     829             : 
     830             :     // shaping state for handling variant fallback features
     831             :     // such as subscript/superscript variant glyphs
     832             :     ShapingState      mShapingState;
     833             : };
     834             : 
     835             : class gfxFontGroup final : public gfxTextRunFactory {
     836             : public:
     837             :     typedef mozilla::unicode::Script Script;
     838             : 
     839             :     static void Shutdown(); // platform must call this to release the languageAtomService
     840             : 
     841             :     gfxFontGroup(const mozilla::FontFamilyList& aFontFamilyList,
     842             :                  const gfxFontStyle* aStyle,
     843             :                  gfxTextPerfMetrics* aTextPerf,
     844             :                  gfxUserFontSet* aUserFontSet,
     845             :                  gfxFloat aDevToCssSize);
     846             : 
     847             :     virtual ~gfxFontGroup();
     848             : 
     849             :     // Returns first valid font in the fontlist or default font.
     850             :     // Initiates userfont loads if userfont not loaded
     851             :     gfxFont* GetFirstValidFont(uint32_t aCh = 0x20);
     852             : 
     853             :     // Returns the first font in the font-group that has an OpenType MATH table,
     854             :     // or null if no such font is available. The GetMathConstant methods may be
     855             :     // called on the returned font.
     856             :     gfxFont *GetFirstMathFont();
     857             : 
     858         142 :     const gfxFontStyle *GetStyle() const { return &mStyle; }
     859             : 
     860             :     gfxFontGroup *Copy(const gfxFontStyle *aStyle);
     861             : 
     862             :     /**
     863             :      * The listed characters should be treated as invisible and zero-width
     864             :      * when creating textruns.
     865             :      */
     866             :     static bool IsInvalidChar(uint8_t ch);
     867             :     static bool IsInvalidChar(char16_t ch);
     868             : 
     869             :     /**
     870             :      * Make a textrun for a given string.
     871             :      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
     872             :      * textrun will copy it.
     873             :      * This calls FetchGlyphExtents on the textrun.
     874             :      */
     875             :     already_AddRefed<gfxTextRun>
     876             :     MakeTextRun(const char16_t *aString, uint32_t aLength,
     877             :                 const Parameters *aParams,
     878             :                 mozilla::gfx::ShapedTextFlags aFlags,
     879             :                 nsTextFrameUtils::Flags aFlags2,
     880             :                 gfxMissingFontRecorder *aMFR);
     881             :     /**
     882             :      * Make a textrun for a given string.
     883             :      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
     884             :      * textrun will copy it.
     885             :      * This calls FetchGlyphExtents on the textrun.
     886             :      */
     887             :     already_AddRefed<gfxTextRun>
     888             :     MakeTextRun(const uint8_t *aString, uint32_t aLength,
     889             :                 const Parameters *aParams,
     890             :                 mozilla::gfx::ShapedTextFlags aFlags,
     891             :                 nsTextFrameUtils::Flags aFlags2,
     892             :                 gfxMissingFontRecorder *aMFR);
     893             : 
     894             :     /**
     895             :      * Textrun creation helper for clients that don't want to pass
     896             :      * a full Parameters record.
     897             :      */
     898             :     template<typename T>
     899             :     already_AddRefed<gfxTextRun>
     900          62 :     MakeTextRun(const T* aString, uint32_t aLength,
     901             :                 DrawTarget* aRefDrawTarget,
     902             :                 int32_t aAppUnitsPerDevUnit,
     903             :                 mozilla::gfx::ShapedTextFlags aFlags,
     904             :                 nsTextFrameUtils::Flags aFlags2,
     905             :                 gfxMissingFontRecorder *aMFR)
     906             :     {
     907             :         gfxTextRunFactory::Parameters params = {
     908             :             aRefDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevUnit
     909          62 :         };
     910          62 :         return MakeTextRun(aString, aLength, &params, aFlags, aFlags2, aMFR);
     911             :     }
     912             : 
     913             :     // Get the (possibly-cached) width of the hyphen character.
     914             :     gfxFloat GetHyphenWidth(const gfxTextRun::PropertyProvider* aProvider);
     915             : 
     916             :     /**
     917             :      * Make a text run representing a single hyphen character.
     918             :      * This will use U+2010 HYPHEN if available in the first font,
     919             :      * otherwise fall back to U+002D HYPHEN-MINUS.
     920             :      * The caller is responsible for deleting the returned text run
     921             :      * when no longer required.
     922             :      */
     923             :     already_AddRefed<gfxTextRun>
     924             :     MakeHyphenTextRun(DrawTarget* aDrawTarget, uint32_t aAppUnitsPerDevUnit);
     925             : 
     926             :     /**
     927             :      * Check whether a given font (specified by its gfxFontEntry)
     928             :      * is already in the fontgroup's list of actual fonts
     929             :      */
     930             :     bool HasFont(const gfxFontEntry *aFontEntry);
     931             : 
     932             :     // This returns the preferred underline for this font group.
     933             :     // Some CJK fonts have wrong underline offset in its metrics.
     934             :     // If this group has such "bad" font, each platform's gfxFontGroup
     935             :     // initialized mUnderlineOffset. The value should be lower value of
     936             :     // first font's metrics and the bad font's metrics. Otherwise, this
     937             :     // returns from first font's metrics.
     938             :     enum { UNDERLINE_OFFSET_NOT_SET = INT16_MAX };
     939             :     gfxFloat GetUnderlineOffset();
     940             : 
     941             :     gfxFont* FindFontForChar(uint32_t ch, uint32_t prevCh, uint32_t aNextCh,
     942             :                              Script aRunScript, gfxFont *aPrevMatchedFont,
     943             :                              uint8_t *aMatchType);
     944             : 
     945             :     gfxUserFontSet* GetUserFontSet();
     946             : 
     947             :     // With downloadable fonts, the composition of the font group can change as fonts are downloaded
     948             :     // for each change in state of the user font set, the generation value is bumped to avoid picking up
     949             :     // previously created text runs in the text run word cache.  For font groups based on stylesheets
     950             :     // with no @font-face rule, this always returns 0.
     951             :     uint64_t GetGeneration();
     952             : 
     953             :     // generation of the latest fontset rebuild, 0 when no fontset present
     954             :     uint64_t GetRebuildGeneration();
     955             : 
     956             :     // used when logging text performance
     957         225 :     gfxTextPerfMetrics *GetTextPerfMetrics() { return mTextPerf; }
     958             : 
     959             :     // This will call UpdateUserFonts() if the user font set is changed.
     960             :     void SetUserFontSet(gfxUserFontSet *aUserFontSet);
     961             : 
     962           0 :     void ClearCachedData()
     963             :     {
     964           0 :         mUnderlineOffset = UNDERLINE_OFFSET_NOT_SET;
     965           0 :         mSkipDrawing = false;
     966           0 :         mHyphenWidth = -1;
     967           0 :         mCachedEllipsisTextRun = nullptr;
     968           0 :     }
     969             : 
     970             :     // If there is a user font set, check to see whether the font list or any
     971             :     // caches need updating.
     972             :     void UpdateUserFonts();
     973             : 
     974             :     // search for a specific userfont in the list of fonts
     975             :     bool ContainsUserFont(const gfxUserFontEntry* aUserFont);
     976             : 
     977         101 :     bool ShouldSkipDrawing() const {
     978         101 :         return mSkipDrawing;
     979             :     }
     980             : 
     981           0 :     class LazyReferenceDrawTargetGetter {
     982             :     public:
     983             :       virtual already_AddRefed<DrawTarget> GetRefDrawTarget() = 0;
     984             :     };
     985             :     // The gfxFontGroup keeps ownership of this textrun.
     986             :     // It is only guaranteed to exist until the next call to GetEllipsisTextRun
     987             :     // (which might use a different appUnitsPerDev value or flags) for the font
     988             :     // group, or until UpdateUserFonts is called, or the fontgroup is destroyed.
     989             :     // Get it/use it/forget it :) - don't keep a reference that might go stale.
     990             :     gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel,
     991             :                                    mozilla::gfx::ShapedTextFlags aFlags,
     992             :                                    LazyReferenceDrawTargetGetter& aRefDrawTargetGetter);
     993             : 
     994             : protected:
     995             :     // search through pref fonts for a character, return nullptr if no matching pref font
     996             :     gfxFont* WhichPrefFontSupportsChar(uint32_t aCh);
     997             : 
     998             :     gfxFont* WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
     999             :                                          Script aRunScript);
    1000             : 
    1001             :     template<typename T>
    1002             :     void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
    1003             :                        const T *aString, uint32_t aLength,
    1004             :                        Script aRunScript,
    1005             :                        mozilla::gfx::ShapedTextFlags aOrientation);
    1006             : 
    1007             :     class FamilyFace {
    1008             :     public:
    1009             :         FamilyFace() : mFamily(nullptr), mFontEntry(nullptr),
    1010             :                        mNeedsBold(false), mFontCreated(false),
    1011             :                        mLoading(false), mInvalid(false),
    1012             :                        mCheckForFallbackFaces(false)
    1013             :         { }
    1014             : 
    1015             :         FamilyFace(gfxFontFamily* aFamily, gfxFont* aFont)
    1016             :             : mFamily(aFamily), mNeedsBold(false), mFontCreated(true),
    1017             :               mLoading(false), mInvalid(false), mCheckForFallbackFaces(false)
    1018             :         {
    1019             :             NS_ASSERTION(aFont, "font pointer must not be null");
    1020             :             NS_ASSERTION(!aFamily ||
    1021             :                          aFamily->ContainsFace(aFont->GetFontEntry()),
    1022             :                          "font is not a member of the given family");
    1023             :             mFont = aFont;
    1024             :             NS_ADDREF(aFont);
    1025             :         }
    1026             : 
    1027          21 :         FamilyFace(gfxFontFamily* aFamily, gfxFontEntry* aFontEntry,
    1028             :                    bool aNeedsBold)
    1029          21 :             : mFamily(aFamily), mNeedsBold(aNeedsBold), mFontCreated(false),
    1030          21 :               mLoading(false), mInvalid(false), mCheckForFallbackFaces(false)
    1031             :         {
    1032          21 :             NS_ASSERTION(aFontEntry, "font entry pointer must not be null");
    1033          21 :             NS_ASSERTION(!aFamily ||
    1034             :                          aFamily->ContainsFace(aFontEntry),
    1035             :                          "font is not a member of the given family");
    1036          21 :             mFontEntry = aFontEntry;
    1037          21 :             NS_ADDREF(aFontEntry);
    1038          21 :         }
    1039             : 
    1040          21 :         FamilyFace(const FamilyFace& aOtherFamilyFace)
    1041          21 :             : mFamily(aOtherFamilyFace.mFamily),
    1042          21 :               mNeedsBold(aOtherFamilyFace.mNeedsBold),
    1043          21 :               mFontCreated(aOtherFamilyFace.mFontCreated),
    1044          21 :               mLoading(aOtherFamilyFace.mLoading),
    1045          21 :               mInvalid(aOtherFamilyFace.mInvalid),
    1046         105 :               mCheckForFallbackFaces(aOtherFamilyFace.mCheckForFallbackFaces)
    1047             :         {
    1048          21 :             if (mFontCreated) {
    1049           0 :                 mFont = aOtherFamilyFace.mFont;
    1050           0 :                 NS_ADDREF(mFont);
    1051             :             } else {
    1052          21 :                 mFontEntry = aOtherFamilyFace.mFontEntry;
    1053          21 :                 NS_IF_ADDREF(mFontEntry);
    1054             :             }
    1055          21 :         }
    1056             : 
    1057          25 :         ~FamilyFace()
    1058          25 :         {
    1059          25 :             if (mFontCreated) {
    1060           1 :                 NS_RELEASE(mFont);
    1061             :             } else {
    1062          24 :                 NS_IF_RELEASE(mFontEntry);
    1063             :             }
    1064          25 :         }
    1065             : 
    1066             :         FamilyFace& operator=(const FamilyFace& aOther)
    1067             :         {
    1068             :             if (mFontCreated) {
    1069             :                 NS_RELEASE(mFont);
    1070             :             } else {
    1071             :                 NS_IF_RELEASE(mFontEntry);
    1072             :             }
    1073             : 
    1074             :             mFamily = aOther.mFamily;
    1075             :             mNeedsBold = aOther.mNeedsBold;
    1076             :             mFontCreated = aOther.mFontCreated;
    1077             :             mLoading = aOther.mLoading;
    1078             :             mInvalid = aOther.mInvalid;
    1079             : 
    1080             :             if (mFontCreated) {
    1081             :                 mFont = aOther.mFont;
    1082             :                 NS_ADDREF(mFont);
    1083             :             } else {
    1084             :                 mFontEntry = aOther.mFontEntry;
    1085             :                 NS_IF_ADDREF(mFontEntry);
    1086             :             }
    1087             : 
    1088             :             return *this;
    1089             :         }
    1090             : 
    1091          26 :         gfxFontFamily* Family() const { return mFamily.get(); }
    1092        1959 :         gfxFont* Font() const {
    1093        1959 :             return mFontCreated ? mFont : nullptr;
    1094             :         }
    1095             : 
    1096          68 :         gfxFontEntry* FontEntry() const {
    1097          68 :             return mFontCreated ? mFont->GetFontEntry() : mFontEntry;
    1098             :         }
    1099             : 
    1100           6 :         bool NeedsBold() const { return mNeedsBold; }
    1101          19 :         bool IsUserFontContainer() const {
    1102          19 :             return FontEntry()->mIsUserFontContainer;
    1103             :         }
    1104         866 :         bool IsLoading() const { return mLoading; }
    1105        1959 :         bool IsInvalid() const { return mInvalid; }
    1106             :         void CheckState(bool& aSkipDrawing);
    1107           0 :         void SetLoading(bool aIsLoading) { mLoading = aIsLoading; }
    1108           0 :         void SetInvalid() { mInvalid = true; }
    1109           0 :         bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
    1110           5 :         void SetCheckForFallbackFaces() { mCheckForFallbackFaces = true; }
    1111             : 
    1112           6 :         void SetFont(gfxFont* aFont)
    1113             :         {
    1114           6 :             NS_ASSERTION(aFont, "font pointer must not be null");
    1115           6 :             NS_ADDREF(aFont);
    1116           6 :             if (mFontCreated) {
    1117           0 :                 NS_RELEASE(mFont);
    1118             :             } else {
    1119           6 :                 NS_IF_RELEASE(mFontEntry);
    1120             :             }
    1121           6 :             mFont = aFont;
    1122           6 :             mFontCreated = true;
    1123           6 :             mLoading = false;
    1124           6 :         }
    1125             : 
    1126             :         bool EqualsUserFont(const gfxUserFontEntry* aUserFont) const;
    1127             : 
    1128             :     private:
    1129             :         RefPtr<gfxFontFamily> mFamily;
    1130             :         // either a font or a font entry exists
    1131             :         union {
    1132             :             gfxFont*            mFont;
    1133             :             gfxFontEntry*       mFontEntry;
    1134             :         };
    1135             :         bool                    mNeedsBold   : 1;
    1136             :         bool                    mFontCreated : 1;
    1137             :         bool                    mLoading     : 1;
    1138             :         bool                    mInvalid     : 1;
    1139             :         bool                    mCheckForFallbackFaces : 1;
    1140             :     };
    1141             : 
    1142             :     // List of font families, either named or generic.
    1143             :     // Generic names map to system pref fonts based on language.
    1144             :     mozilla::FontFamilyList mFamilyList;
    1145             : 
    1146             :     // Fontlist containing a font entry for each family found. gfxFont objects
    1147             :     // are created as needed and userfont loads are initiated when needed.
    1148             :     // Code should be careful about addressing this array directly.
    1149             :     nsTArray<FamilyFace> mFonts;
    1150             : 
    1151             :     RefPtr<gfxFont> mDefaultFont;
    1152             :     gfxFontStyle mStyle;
    1153             : 
    1154             :     gfxFloat mUnderlineOffset;
    1155             :     gfxFloat mHyphenWidth;
    1156             :     gfxFloat mDevToCssSize;
    1157             : 
    1158             :     RefPtr<gfxUserFontSet> mUserFontSet;
    1159             :     uint64_t mCurrGeneration;  // track the current user font set generation, rebuild font list if needed
    1160             : 
    1161             :     gfxTextPerfMetrics *mTextPerf;
    1162             : 
    1163             :     // Cache a textrun representing an ellipsis (useful for CSS text-overflow)
    1164             :     // at a specific appUnitsPerDevPixel size and orientation
    1165             :     RefPtr<gfxTextRun>   mCachedEllipsisTextRun;
    1166             : 
    1167             :     // cache the most recent pref font to avoid general pref font lookup
    1168             :     RefPtr<gfxFontFamily> mLastPrefFamily;
    1169             :     RefPtr<gfxFont>       mLastPrefFont;
    1170             :     eFontPrefLang           mLastPrefLang;       // lang group for last pref font
    1171             :     eFontPrefLang           mPageLang;
    1172             :     bool                    mLastPrefFirstFont;  // is this the first font in the list of pref fonts for this lang group?
    1173             : 
    1174             :     bool                    mSkipDrawing; // hide text while waiting for a font
    1175             :                                           // download to complete (or fallback
    1176             :                                           // timer to fire)
    1177             : 
    1178             :     /**
    1179             :      * Textrun creation short-cuts for special cases where we don't need to
    1180             :      * call a font shaper to generate glyphs.
    1181             :      */
    1182             :     already_AddRefed<gfxTextRun>
    1183             :     MakeEmptyTextRun(const Parameters *aParams,
    1184             :                      mozilla::gfx::ShapedTextFlags aFlags,
    1185             :                      nsTextFrameUtils::Flags aFlags2);
    1186             : 
    1187             :     already_AddRefed<gfxTextRun>
    1188             :     MakeSpaceTextRun(const Parameters *aParams,
    1189             :                      mozilla::gfx::ShapedTextFlags aFlags,
    1190             :                      nsTextFrameUtils::Flags aFlags2);
    1191             : 
    1192             :     already_AddRefed<gfxTextRun>
    1193             :     MakeBlankTextRun(uint32_t aLength, const Parameters *aParams,
    1194             :                      mozilla::gfx::ShapedTextFlags aFlags,
    1195             :                      nsTextFrameUtils::Flags aFlags2);
    1196             : 
    1197             :     // Initialize the list of fonts
    1198             :     void BuildFontList();
    1199             : 
    1200             :     // Get the font at index i within the fontlist.
    1201             :     // Will initiate userfont load if not already loaded.
    1202             :     // May return null if userfont not loaded or if font invalid
    1203             :     gfxFont* GetFontAt(int32_t i, uint32_t aCh = 0x20);
    1204             : 
    1205             :     // Whether there's a font loading for a given family in the fontlist
    1206             :     // for a given character
    1207             :     bool FontLoadingForFamily(gfxFontFamily* aFamily, uint32_t aCh) const;
    1208             : 
    1209             :     // will always return a font or force a shutdown
    1210             :     gfxFont* GetDefaultFont();
    1211             : 
    1212             :     // Init this font group's font metrics. If there no bad fonts, you don't need to call this.
    1213             :     // But if there are one or more bad fonts which have bad underline offset,
    1214             :     // you should call this with the *first* bad font.
    1215             :     void InitMetricsForBadFont(gfxFont* aBadFont);
    1216             : 
    1217             :     // Set up the textrun glyphs for an entire text run:
    1218             :     // find script runs, and then call InitScriptRun for each
    1219             :     template<typename T>
    1220             :     void InitTextRun(DrawTarget* aDrawTarget,
    1221             :                      gfxTextRun *aTextRun,
    1222             :                      const T *aString,
    1223             :                      uint32_t aLength,
    1224             :                      gfxMissingFontRecorder *aMFR);
    1225             : 
    1226             :     // InitTextRun helper to handle a single script run, by finding font ranges
    1227             :     // and calling each font's InitTextRun() as appropriate
    1228             :     template<typename T>
    1229             :     void InitScriptRun(DrawTarget* aDrawTarget,
    1230             :                        gfxTextRun *aTextRun,
    1231             :                        const T *aString,
    1232             :                        uint32_t aScriptRunStart,
    1233             :                        uint32_t aScriptRunEnd,
    1234             :                        Script aRunScript,
    1235             :                        gfxMissingFontRecorder *aMFR);
    1236             : 
    1237             :     // Helper for font-matching:
    1238             :     // search all faces in a family for a fallback in cases where it's unclear
    1239             :     // whether the family might have a font for a given character
    1240             :     gfxFont*
    1241             :     FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh,
    1242             :                             Script aRunScript);
    1243             : 
    1244             :    // helper methods for looking up fonts
    1245             : 
    1246             :     // lookup and add a font with a given name (i.e. *not* a generic!)
    1247             :     void AddPlatformFont(const nsAString& aName,
    1248             :                          nsTArray<gfxFontFamily*>& aFamilyList);
    1249             : 
    1250             :     // do style selection and add entries to list
    1251             :     void AddFamilyToFontList(gfxFontFamily* aFamily);
    1252             : };
    1253             : 
    1254             : // A "missing font recorder" is to be used during text-run creation to keep
    1255             : // a record of any scripts encountered for which font coverage was lacking;
    1256             : // when Flush() is called, it sends a notification that front-end code can use
    1257             : // to download fonts on demand (or whatever else it wants to do).
    1258             : 
    1259             : #define GFX_MISSING_FONTS_NOTIFY_PREF "gfx.missing_fonts.notify"
    1260             : 
    1261             : class gfxMissingFontRecorder {
    1262             : public:
    1263           0 :     gfxMissingFontRecorder()
    1264           0 :     {
    1265           0 :         MOZ_COUNT_CTOR(gfxMissingFontRecorder);
    1266           0 :         memset(&mMissingFonts, 0, sizeof(mMissingFonts));
    1267           0 :     }
    1268             : 
    1269           0 :     ~gfxMissingFontRecorder()
    1270           0 :     {
    1271             : #ifdef DEBUG
    1272           0 :         for (uint32_t i = 0; i < kNumScriptBitsWords; i++) {
    1273           0 :             NS_ASSERTION(mMissingFonts[i] == 0,
    1274             :                          "failed to flush the missing-font recorder");
    1275             :         }
    1276             : #endif
    1277           0 :         MOZ_COUNT_DTOR(gfxMissingFontRecorder);
    1278           0 :     }
    1279             : 
    1280             :     // record this script code in our mMissingFonts bitset
    1281           0 :     void RecordScript(mozilla::unicode::Script aScriptCode)
    1282             :     {
    1283           0 :         mMissingFonts[static_cast<uint32_t>(aScriptCode) >> 5] |=
    1284           0 :             (1 << (static_cast<uint32_t>(aScriptCode) & 0x1f));
    1285           0 :     }
    1286             : 
    1287             :     // send a notification of any missing-scripts that have been
    1288             :     // recorded, and clear the mMissingFonts set for re-use
    1289             :     void Flush();
    1290             : 
    1291             :     // forget any missing-scripts that have been recorded up to now;
    1292             :     // called before discarding a recorder we no longer care about
    1293           0 :     void Clear()
    1294             :     {
    1295           0 :         memset(&mMissingFonts, 0, sizeof(mMissingFonts));
    1296           0 :     }
    1297             : 
    1298             : private:
    1299             :     // Number of 32-bit words needed for the missing-script flags
    1300             :     static const uint32_t kNumScriptBitsWords =
    1301             :         ((static_cast<int>(mozilla::unicode::Script::NUM_SCRIPT_CODES) + 31) / 32);
    1302             :     uint32_t mMissingFonts[kNumScriptBitsWords];
    1303             : };
    1304             : 
    1305             : #endif

Generated by: LCOV version 1.13