LCOV - code coverage report
Current view: top level - gfx/thebes - gfxFont.h (source / functions) Hit Total Coverage
Test: output.info Lines: 276 461 59.9 %
Date: 2017-07-14 16:53:18 Functions: 102 159 64.2 %
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_FONT_H
       8             : #define GFX_FONT_H
       9             : 
      10             : #include "gfxTypes.h"
      11             : #include "gfxFontEntry.h"
      12             : #include "gfxFontVariations.h"
      13             : #include "nsString.h"
      14             : #include "gfxPoint.h"
      15             : #include "gfxPattern.h"
      16             : #include "nsTArray.h"
      17             : #include "nsTHashtable.h"
      18             : #include "nsHashKeys.h"
      19             : #include "gfxRect.h"
      20             : #include "nsExpirationTracker.h"
      21             : #include "gfxPlatform.h"
      22             : #include "nsIAtom.h"
      23             : #include "mozilla/HashFunctions.h"
      24             : #include "nsIMemoryReporter.h"
      25             : #include "nsIObserver.h"
      26             : #include "mozilla/MemoryReporting.h"
      27             : #include "mozilla/Attributes.h"
      28             : #include "mozilla/TypedEnumBits.h"
      29             : #include "MainThreadUtils.h"
      30             : #include <algorithm>
      31             : #include "DrawMode.h"
      32             : #include "nsDataHashtable.h"
      33             : #include "harfbuzz/hb.h"
      34             : #include "mozilla/gfx/2D.h"
      35             : #include "nsColor.h"
      36             : 
      37             : typedef struct _cairo cairo_t;
      38             : typedef struct _cairo_scaled_font cairo_scaled_font_t;
      39             : //typedef struct gr_face            gr_face;
      40             : 
      41             : #ifdef DEBUG
      42             : #include <stdio.h>
      43             : #endif
      44             : 
      45             : class gfxContext;
      46             : class gfxTextRun;
      47             : class gfxFont;
      48             : class gfxGlyphExtents;
      49             : class gfxShapedText;
      50             : class gfxShapedWord;
      51             : class gfxSkipChars;
      52             : class gfxMathTable;
      53             : 
      54             : #define FONT_MAX_SIZE                  2000.0
      55             : 
      56             : #define NO_FONT_LANGUAGE_OVERRIDE      0
      57             : 
      58             : #define SMALL_CAPS_SCALE_FACTOR        0.8
      59             : 
      60             : // The skew factor used for synthetic-italic [oblique] fonts;
      61             : // we use a platform-dependent value to harmonize with the platform's own APIs.
      62             : #ifdef XP_WIN
      63             : #define OBLIQUE_SKEW_FACTOR  0.3
      64             : #elif defined(MOZ_WIDGET_GTK)
      65             : #define OBLIQUE_SKEW_FACTOR  0.2
      66             : #else
      67             : #define OBLIQUE_SKEW_FACTOR  0.25
      68             : #endif
      69             : 
      70             : struct gfxTextRunDrawCallbacks;
      71             : 
      72             : namespace mozilla {
      73             : class SVGContextPaint;
      74             : namespace gfx {
      75             : class GlyphRenderingOptions;
      76             : } // namespace gfx
      77             : } // namespace mozilla
      78             : 
      79          36 : struct gfxFontStyle {
      80             :     gfxFontStyle();
      81             :     gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
      82             :                  gfxFloat aSize, nsIAtom *aLanguage, bool aExplicitLanguage,
      83             :                  float aSizeAdjust, bool aSystemFont,
      84             :                  bool aPrinterFont,
      85             :                  bool aWeightSynthesis, bool aStyleSynthesis,
      86             :                  uint32_t aLanguageOverride);
      87             : 
      88             :     // the language (may be an internal langGroup code rather than an actual
      89             :     // language code) specified in the document or element's lang property,
      90             :     // or inferred from the charset
      91             :     RefPtr<nsIAtom> language;
      92             : 
      93             :     // Features are composed of (1) features from style rules (2) features
      94             :     // from feature settings rules and (3) family-specific features.  (1) and
      95             :     // (3) are guaranteed to be mutually exclusive
      96             : 
      97             :     // custom opentype feature settings
      98             :     nsTArray<gfxFontFeature> featureSettings;
      99             : 
     100             :     // Some font-variant property values require font-specific settings
     101             :     // defined via @font-feature-values rules.  These are resolved after
     102             :     // font matching occurs.
     103             : 
     104             :     // -- list of value tags for specific alternate features
     105             :     nsTArray<gfxAlternateValue> alternateValues;
     106             : 
     107             :     // -- object used to look these up once the font is matched
     108             :     RefPtr<gfxFontFeatureValueSet> featureValueLookup;
     109             : 
     110             :     // opentype variation settings
     111             :     nsTArray<gfxFontVariation> variationSettings;
     112             : 
     113             :     // The logical size of the font, in pixels
     114             :     gfxFloat size;
     115             : 
     116             :     // The aspect-value (ie., the ratio actualsize:actualxheight) that any
     117             :     // actual physical font created from this font structure must have when
     118             :     // rendering or measuring a string. A value of -1.0 means no adjustment
     119             :     // needs to be done; otherwise the value must be nonnegative.
     120             :     float sizeAdjust;
     121             : 
     122             :     // baseline offset, used when simulating sub/superscript glyphs
     123             :     float baselineOffset;
     124             : 
     125             :     // Language system tag, to override document language;
     126             :     // an OpenType "language system" tag represented as a 32-bit integer
     127             :     // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
     128             :     // Normally 0, so font rendering will use the document or element language
     129             :     // (see above) to control any language-specific rendering, but the author
     130             :     // can override this for cases where the options implemented in the font
     131             :     // do not directly match the actual language. (E.g. lang may be Macedonian,
     132             :     // but the font in use does not explicitly support this; the author can
     133             :     // use font-language-override to request the Serbian option in the font
     134             :     // in order to get correct glyph shapes.)
     135             :     uint32_t languageOverride;
     136             : 
     137             :     // The weight of the font: 100, 200, ... 900.
     138             :     uint16_t weight;
     139             : 
     140             :     // The stretch of the font (the sum of various NS_FONT_STRETCH_*
     141             :     // constants; see gfxFontConstants.h).
     142             :     int8_t stretch;
     143             : 
     144             :     // The style of font (normal, italic, oblique)
     145             :     uint8_t style;
     146             : 
     147             :     // caps variant (small-caps, petite-caps, etc.)
     148             :     uint8_t variantCaps;
     149             : 
     150             :     // sub/superscript variant
     151             :     uint8_t variantSubSuper;
     152             : 
     153             :     // Say that this font is a system font and therefore does not
     154             :     // require certain fixup that we do for fonts from untrusted
     155             :     // sources.
     156             :     bool systemFont : 1;
     157             : 
     158             :     // Say that this font is used for print or print preview.
     159             :     bool printerFont : 1;
     160             : 
     161             :     // Used to imitate -webkit-font-smoothing: antialiased
     162             :     bool useGrayscaleAntialiasing : 1;
     163             : 
     164             :     // Whether synthetic styles are allowed
     165             :     bool allowSyntheticWeight : 1;
     166             :     bool allowSyntheticStyle : 1;
     167             : 
     168             :     // some variant features require fallback which complicates the shaping
     169             :     // code, so set up a bool to indicate when shaping with fallback is needed
     170             :     bool noFallbackVariantFeatures : 1;
     171             : 
     172             :     // whether the |language| field comes from explicit lang tagging in the
     173             :     // document, or was inferred from charset/system locale
     174             :     bool explicitLanguage : 1;
     175             : 
     176             :     // Return the final adjusted font size for the given aspect ratio.
     177             :     // Not meant to be called when sizeAdjust = -1.0.
     178           0 :     gfxFloat GetAdjustedSize(gfxFloat aspect) const {
     179           0 :         NS_ASSERTION(sizeAdjust >= 0.0, "Not meant to be called when sizeAdjust = -1.0");
     180           0 :         gfxFloat adjustedSize = std::max(NS_round(size*(sizeAdjust/aspect)), 1.0);
     181           0 :         return std::min(adjustedSize, FONT_MAX_SIZE);
     182             :     }
     183             : 
     184          22 :     PLDHashNumber Hash() const {
     185          44 :         return ((style + (systemFont << 7) +
     186          44 :             (weight << 8)) + uint32_t(size*1000) + uint32_t(sizeAdjust*1000)) ^
     187          22 :             nsISupportsHashKey::HashKey(language);
     188             :     }
     189             : 
     190             :     int8_t ComputeWeight() const;
     191             : 
     192             :     // Adjust this style to simulate sub/superscript (as requested in the
     193             :     // variantSubSuper field) using size and baselineOffset instead.
     194             :     void AdjustForSubSuperscript(int32_t aAppUnitsPerDevPixel);
     195             : 
     196           9 :     bool Equals(const gfxFontStyle& other) const {
     197             :         return
     198           9 :             (*reinterpret_cast<const uint64_t*>(&size) ==
     199          18 :              *reinterpret_cast<const uint64_t*>(&other.size)) &&
     200          18 :             (style == other.style) &&
     201          18 :             (weight == other.weight) &&
     202          18 :             (stretch == other.stretch) &&
     203          18 :             (variantCaps == other.variantCaps) &&
     204          18 :             (variantSubSuper == other.variantSubSuper) &&
     205          18 :             (allowSyntheticWeight == other.allowSyntheticWeight) &&
     206          18 :             (allowSyntheticStyle == other.allowSyntheticStyle) &&
     207          18 :             (systemFont == other.systemFont) &&
     208          18 :             (printerFont == other.printerFont) &&
     209          18 :             (useGrayscaleAntialiasing == other.useGrayscaleAntialiasing) &&
     210          18 :             (explicitLanguage == other.explicitLanguage) &&
     211          18 :             (language == other.language) &&
     212          18 :             (baselineOffset == other.baselineOffset) &&
     213           9 :             (*reinterpret_cast<const uint32_t*>(&sizeAdjust) ==
     214          18 :              *reinterpret_cast<const uint32_t*>(&other.sizeAdjust)) &&
     215          18 :             (featureSettings == other.featureSettings) &&
     216          18 :             (alternateValues == other.alternateValues) &&
     217          18 :             (featureValueLookup == other.featureValueLookup) &&
     218          27 :             (variationSettings == other.variationSettings) &&
     219          18 :             (languageOverride == other.languageOverride);
     220             :     }
     221             : };
     222             : 
     223             : 
     224             : /**
     225             :  * Font cache design:
     226             :  * 
     227             :  * The mFonts hashtable contains most fonts, indexed by (gfxFontEntry*, style).
     228             :  * It does not add a reference to the fonts it contains.
     229             :  * When a font's refcount decreases to zero, instead of deleting it we
     230             :  * add it to our expiration tracker.
     231             :  * The expiration tracker tracks fonts with zero refcount. After a certain
     232             :  * period of time, such fonts expire and are deleted.
     233             :  *
     234             :  * We're using 3 generations with a ten-second generation interval, so
     235             :  * zero-refcount fonts will be deleted 20-30 seconds after their refcount
     236             :  * goes to zero, if timer events fire in a timely manner.
     237             :  *
     238             :  * The font cache also handles timed expiration of cached ShapedWords
     239             :  * for "persistent" fonts: it has a repeating timer, and notifies
     240             :  * each cached font to "age" its shaped words. The words will be released
     241             :  * by the fonts if they get aged three times without being re-used in the
     242             :  * meantime.
     243             :  *
     244             :  * Note that the ShapedWord timeout is much larger than the font timeout,
     245             :  * so that in the case of a short-lived font, we'll discard the gfxFont
     246             :  * completely, with all its words, and avoid the cost of aging the words
     247             :  * individually. That only happens with longer-lived fonts.
     248             :  */
     249             : struct FontCacheSizes {
     250           0 :     FontCacheSizes()
     251           0 :         : mFontInstances(0), mShapedWords(0)
     252           0 :     { }
     253             : 
     254             :     size_t mFontInstances; // memory used by instances of gfxFont subclasses
     255             :     size_t mShapedWords; // memory used by the per-font shapedWord caches
     256             : };
     257             : 
     258             : class gfxFontCache final : public nsExpirationTracker<gfxFont,3> {
     259             : public:
     260             :     enum {
     261             :         FONT_TIMEOUT_SECONDS = 10,
     262             :         SHAPED_WORD_TIMEOUT_SECONDS = 60
     263             :     };
     264             : 
     265             :     explicit gfxFontCache(nsIEventTarget* aEventTarget);
     266             :     ~gfxFontCache();
     267             : 
     268             :     /*
     269             :      * Get the global gfxFontCache.  You must call Init() before
     270             :      * calling this method --- the result will not be null.
     271             :      */
     272          40 :     static gfxFontCache* GetCache() {
     273          40 :         return gGlobalCache;
     274             :     }
     275             : 
     276             :     static nsresult Init();
     277             :     // It's OK to call this even if Init() has not been called.
     278             :     static void Shutdown();
     279             : 
     280             :     // Look up a font in the cache. Returns null if there's nothing matching
     281             :     // in the cache
     282             :     gfxFont* Lookup(const gfxFontEntry* aFontEntry,
     283             :                     const gfxFontStyle* aStyle,
     284             :                     const gfxCharacterMap* aUnicodeRangeMap);
     285             : 
     286             :     // We created a new font (presumably because Lookup returned null);
     287             :     // put it in the cache. The font's refcount should be nonzero. It is
     288             :     // allowable to add a new font even if there is one already in the
     289             :     // cache with the same key; we'll forget about the old one.
     290             :     void AddNew(gfxFont *aFont);
     291             : 
     292             :     // The font's refcount has gone to zero; give ownership of it to
     293             :     // the cache. We delete it if it's not acquired again after a certain
     294             :     // amount of time.
     295             :     void NotifyReleased(gfxFont *aFont);
     296             : 
     297             :     // This gets called when the timeout has expired on a zero-refcount
     298             :     // font; we just delete it.
     299             :     virtual void NotifyExpired(gfxFont *aFont) override;
     300             : 
     301             :     // Cleans out the hashtable and removes expired fonts waiting for cleanup.
     302             :     // Other gfxFont objects may be still in use but they will be pushed
     303             :     // into the expiration queues and removed.
     304             :     void Flush() {
     305             :         mFonts.Clear();
     306             :         AgeAllGenerations();
     307             :     }
     308             : 
     309             :     void FlushShapedWordCaches();
     310             :     void NotifyGlyphsChanged();
     311             : 
     312             :     void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
     313             :                                 FontCacheSizes* aSizes) const;
     314             :     void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
     315             :                                 FontCacheSizes* aSizes) const;
     316             : 
     317             : protected:
     318           3 :     class MemoryReporter final : public nsIMemoryReporter
     319             :     {
     320           0 :         ~MemoryReporter() {}
     321             :     public:
     322             :         NS_DECL_ISUPPORTS
     323             :         NS_DECL_NSIMEMORYREPORTER
     324             :     };
     325             : 
     326             :     // Observer for notifications that the font cache cares about
     327           3 :     class Observer final
     328             :         : public nsIObserver
     329             :     {
     330           0 :         ~Observer() {}
     331             :     public:
     332             :         NS_DECL_ISUPPORTS
     333             :         NS_DECL_NSIOBSERVER
     334             :     };
     335             : 
     336             :     void DestroyFont(gfxFont *aFont);
     337             : 
     338             :     static gfxFontCache *gGlobalCache;
     339             : 
     340             :     struct Key {
     341             :         const gfxFontEntry* mFontEntry;
     342             :         const gfxFontStyle* mStyle;
     343             :         const gfxCharacterMap* mUnicodeRangeMap;
     344          17 :         Key(const gfxFontEntry* aFontEntry, const gfxFontStyle* aStyle,
     345             :             const gfxCharacterMap* aUnicodeRangeMap)
     346          17 :             : mFontEntry(aFontEntry), mStyle(aStyle),
     347          17 :               mUnicodeRangeMap(aUnicodeRangeMap)
     348          17 :         {}
     349             :     };
     350             : 
     351             :     class HashEntry : public PLDHashEntryHdr {
     352             :     public:
     353             :         typedef const Key& KeyType;
     354             :         typedef const Key* KeyTypePointer;
     355             : 
     356             :         // When constructing a new entry in the hashtable, we'll leave this
     357             :         // blank. The caller of Put() will fill this in.
     358           8 :         explicit HashEntry(KeyTypePointer aStr) : mFont(nullptr) { }
     359             :         HashEntry(const HashEntry& toCopy) : mFont(toCopy.mFont) { }
     360           0 :         ~HashEntry() { }
     361             : 
     362             :         bool KeyEquals(const KeyTypePointer aKey) const;
     363          25 :         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
     364          22 :         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
     365          22 :             return mozilla::HashGeneric(aKey->mStyle->Hash(), aKey->mFontEntry,
     366          44 :                                         aKey->mUnicodeRangeMap);
     367             :         }
     368             :         enum { ALLOW_MEMMOVE = true };
     369             : 
     370             :         gfxFont* mFont;
     371             :     };
     372             : 
     373             :     nsTHashtable<HashEntry> mFonts;
     374             : 
     375             :     static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
     376             :     nsCOMPtr<nsITimer>      mWordCacheExpirationTimer;
     377             : };
     378             : 
     379             : class gfxTextPerfMetrics {
     380             : public:
     381             : 
     382             :     struct TextCounts {
     383             :         uint32_t    numContentTextRuns;
     384             :         uint32_t    numChromeTextRuns;
     385             :         uint32_t    numChars;
     386             :         uint32_t    maxTextRunLen;
     387             :         uint32_t    wordCacheSpaceRules;
     388             :         uint32_t    wordCacheLong;
     389             :         uint32_t    wordCacheHit;
     390             :         uint32_t    wordCacheMiss;
     391             :         uint32_t    fallbackPrefs;
     392             :         uint32_t    fallbackSystem;
     393             :         uint32_t    textrunConst;
     394             :         uint32_t    textrunDestr;
     395             :         uint32_t    genericLookups;
     396             :     };
     397             : 
     398             :     uint32_t reflowCount;
     399             : 
     400             :     // counts per reflow operation
     401             :     TextCounts current;
     402             : 
     403             :     // totals for the lifetime of a document
     404             :     TextCounts cumulative;
     405             : 
     406           0 :     gfxTextPerfMetrics() {
     407           0 :         memset(this, 0, sizeof(gfxTextPerfMetrics));
     408           0 :     }
     409             : 
     410             :     // add current totals to cumulative ones
     411           0 :     void Accumulate() {
     412           0 :         if (current.numChars == 0) {
     413           0 :             return;
     414             :         }
     415           0 :         cumulative.numContentTextRuns += current.numContentTextRuns;
     416           0 :         cumulative.numChromeTextRuns += current.numChromeTextRuns;
     417           0 :         cumulative.numChars += current.numChars;
     418           0 :         if (current.maxTextRunLen > cumulative.maxTextRunLen) {
     419           0 :             cumulative.maxTextRunLen = current.maxTextRunLen;
     420             :         }
     421           0 :         cumulative.wordCacheSpaceRules += current.wordCacheSpaceRules;
     422           0 :         cumulative.wordCacheLong += current.wordCacheLong;
     423           0 :         cumulative.wordCacheHit += current.wordCacheHit;
     424           0 :         cumulative.wordCacheMiss += current.wordCacheMiss;
     425           0 :         cumulative.fallbackPrefs += current.fallbackPrefs;
     426           0 :         cumulative.fallbackSystem += current.fallbackSystem;
     427           0 :         cumulative.textrunConst += current.textrunConst;
     428           0 :         cumulative.textrunDestr += current.textrunDestr;
     429           0 :         cumulative.genericLookups += current.genericLookups;
     430           0 :         memset(&current, 0, sizeof(current));
     431             :     }
     432             : };
     433             : 
     434             : namespace mozilla {
     435             : namespace gfx {
     436             : // Flags that live in the gfxShapedText::mFlags field.
     437             : // (Note that gfxTextRun has an additional mFlags2 field for use
     438             : // by textrun clients like nsTextFrame.)
     439             : enum class ShapedTextFlags : uint16_t {
     440             :     /**
     441             :      * When set, the text is RTL.
     442             :      */
     443             :     TEXT_IS_RTL                  = 0x0001,
     444             :     /**
     445             :      * When set, spacing is enabled and the textrun needs to call GetSpacing
     446             :      * on the spacing provider.
     447             :      */
     448             :     TEXT_ENABLE_SPACING          = 0x0002,
     449             :     /**
     450             :      * When set, the text has no characters above 255 and it is stored
     451             :      * in the textrun in 8-bit format.
     452             :      */
     453             :     TEXT_IS_8BIT                 = 0x0004,
     454             :     /**
     455             :      * When set, GetHyphenationBreaks may return true for some character
     456             :      * positions, otherwise it will always return false for all characters.
     457             :      */
     458             :     TEXT_ENABLE_HYPHEN_BREAKS    = 0x0008,
     459             :     /**
     460             :      * When set, the RunMetrics::mBoundingBox field will be initialized
     461             :      * properly based on glyph extents, in particular, glyph extents that
     462             :      * overflow the standard font-box (the box defined by the ascent, descent
     463             :      * and advance width of the glyph). When not set, it may just be the
     464             :      * standard font-box even if glyphs overflow.
     465             :      */
     466             :     TEXT_NEED_BOUNDING_BOX       = 0x0010,
     467             :     /**
     468             :      * When set, optional ligatures are disabled. Ligatures that are
     469             :      * required for legible text should still be enabled.
     470             :      */
     471             :     TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0020,
     472             :     /**
     473             :      * When set, the textrun should favour speed of construction over
     474             :      * quality. This may involve disabling ligatures and/or kerning or
     475             :      * other effects.
     476             :      */
     477             :     TEXT_OPTIMIZE_SPEED          = 0x0040,
     478             :     /**
     479             :      * When set, the textrun should discard control characters instead of
     480             :      * turning them into hexboxes.
     481             :      */
     482             :     TEXT_HIDE_CONTROL_CHARACTERS = 0x0080,
     483             : 
     484             :     /**
     485             :      * nsTextFrameThebes sets these, but they're defined here rather than
     486             :      * in nsTextFrameUtils.h because ShapedWord creation/caching also needs
     487             :      * to check the _INCOMING flag
     488             :      */
     489             :     TEXT_TRAILING_ARABICCHAR     = 0x0100,
     490             :     /**
     491             :      * When set, the previous character for this textrun was an Arabic
     492             :      * character.  This is used for the context detection necessary for
     493             :      * bidi.numeral implementation.
     494             :      */
     495             :     TEXT_INCOMING_ARABICCHAR     = 0x0200,
     496             : 
     497             :     /**
     498             :      * Set if the textrun should use the OpenType 'math' script.
     499             :      */
     500             :     TEXT_USE_MATH_SCRIPT         = 0x0400,
     501             : 
     502             :     /*
     503             :      * Bit 0x0800 is currently unused.
     504             :      */
     505             : 
     506             :     /**
     507             :      * Field for orientation of the textrun and glyphs within it.
     508             :      * Possible values of the TEXT_ORIENT_MASK field:
     509             :      *   TEXT_ORIENT_HORIZONTAL
     510             :      *   TEXT_ORIENT_VERTICAL_UPRIGHT
     511             :      *   TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT
     512             :      *   TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT
     513             :      *   TEXT_ORIENT_VERTICAL_MIXED
     514             :      * For all VERTICAL settings, the x and y coordinates of glyph
     515             :      * positions are exchanged, so that simple advances are vertical.
     516             :      *
     517             :      * The MIXED value indicates vertical textRuns for which the CSS
     518             :      * text-orientation property is 'mixed', but is never used for
     519             :      * individual glyphRuns; it will be resolved to either UPRIGHT
     520             :      * or SIDEWAYS_RIGHT according to the UTR50 properties of the
     521             :      * characters, and separate glyphRuns created for the resulting
     522             :      * glyph orientations.
     523             :      */
     524             :     TEXT_ORIENT_MASK                    = 0x7000,
     525             :     TEXT_ORIENT_HORIZONTAL              = 0x0000,
     526             :     TEXT_ORIENT_VERTICAL_UPRIGHT        = 0x1000,
     527             :     TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT = 0x2000,
     528             :     TEXT_ORIENT_VERTICAL_MIXED          = 0x3000,
     529             :     TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT  = 0x4000,
     530             : };
     531             : 
     532        2239 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ShapedTextFlags)
     533             : } // namespace gfx
     534             : } // namespace mozilla
     535             : 
     536           6 : class gfxTextRunFactory {
     537             :     // Used by stylo
     538         161 :     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxTextRunFactory)
     539             : 
     540             : public:
     541             :     typedef mozilla::gfx::DrawTarget DrawTarget;
     542             : 
     543             :     /**
     544             :      * This record contains all the parameters needed to initialize a textrun.
     545             :      */
     546             :     struct Parameters {
     547             :         // Shape text params suggesting where the textrun will be rendered
     548             :         DrawTarget   *mDrawTarget;
     549             :         // Pointer to arbitrary user data (which should outlive the textrun)
     550             :         void         *mUserData;
     551             :         // A description of which characters have been stripped from the original
     552             :         // DOM string to produce the characters in the textrun. May be null
     553             :         // if that information is not relevant.
     554             :         gfxSkipChars *mSkipChars;
     555             :         // A list of where linebreaks are currently placed in the textrun. May
     556             :         // be null if mInitialBreakCount is zero.
     557             :         uint32_t     *mInitialBreaks;
     558             :         uint32_t      mInitialBreakCount;
     559             :         // The ratio to use to convert device pixels to application layout units
     560             :         int32_t       mAppUnitsPerDevUnit;
     561             :     };
     562             : 
     563             : protected:
     564             :     // Protected destructor, to discourage deletion outside of Release():
     565             :     virtual ~gfxTextRunFactory();
     566             : };
     567             : 
     568         213 : struct gfxTextRange {
     569             :     enum {
     570             :         // flags for recording the kind of font-matching that was used
     571             :         kFontGroup      = 0x0001,
     572             :         kPrefsFallback  = 0x0002,
     573             :         kSystemFallback = 0x0004
     574             :     };
     575          71 :     gfxTextRange(uint32_t aStart, uint32_t aEnd,
     576             :                  gfxFont* aFont, uint8_t aMatchType,
     577             :                  mozilla::gfx::ShapedTextFlags aOrientation)
     578          71 :         : start(aStart),
     579             :           end(aEnd),
     580             :           font(aFont),
     581             :           matchType(aMatchType),
     582          71 :           orientation(aOrientation)
     583          71 :     { }
     584          71 :     uint32_t Length() const { return end - start; }
     585             :     uint32_t start, end;
     586             :     RefPtr<gfxFont> font;
     587             :     uint8_t matchType;
     588             :     mozilla::gfx::ShapedTextFlags orientation;
     589             : };
     590             : 
     591             : /**
     592             :  * gfxFontShaper
     593             :  *
     594             :  * This class implements text shaping (character to glyph mapping and
     595             :  * glyph layout). There is a gfxFontShaper subclass for each text layout
     596             :  * technology (uniscribe, core text, harfbuzz,....) we support.
     597             :  *
     598             :  * The shaper is responsible for setting up glyph data in gfxTextRuns.
     599             :  *
     600             :  * A generic, platform-independent shaper relies only on the standard
     601             :  * gfxFont interface and can work with any concrete subclass of gfxFont.
     602             :  *
     603             :  * Platform-specific implementations designed to interface to platform
     604             :  * shaping APIs such as Uniscribe or CoreText may rely on features of a
     605             :  * specific font subclass to access native font references
     606             :  * (such as CTFont, HFONT, DWriteFont, etc).
     607             :  */
     608             : 
     609             : class gfxFontShaper {
     610             : public:
     611             :     typedef mozilla::gfx::DrawTarget DrawTarget;
     612             :     typedef mozilla::unicode::Script Script;
     613             : 
     614             :     enum class RoundingFlags : uint8_t {
     615             :         kRoundX = 0x01,
     616             :         kRoundY = 0x02
     617             :     };
     618             : 
     619           2 :     explicit gfxFontShaper(gfxFont *aFont)
     620           2 :         : mFont(aFont)
     621             :     {
     622           2 :         NS_ASSERTION(aFont, "shaper requires a valid font!");
     623           2 :     }
     624             : 
     625           0 :     virtual ~gfxFontShaper() { }
     626             : 
     627             :     // Shape a piece of text and store the resulting glyph data into
     628             :     // aShapedText. Parameters aOffset/aLength indicate the range of
     629             :     // aShapedText to be updated; aLength is also the length of aText.
     630             :     virtual bool ShapeText(DrawTarget     *aDrawTarget,
     631             :                            const char16_t *aText,
     632             :                            uint32_t        aOffset,
     633             :                            uint32_t        aLength,
     634             :                            Script          aScript,
     635             :                            bool            aVertical,
     636             :                            RoundingFlags   aRounding,
     637             :                            gfxShapedText  *aShapedText) = 0;
     638             : 
     639         265 :     gfxFont *GetFont() const { return mFont; }
     640             : 
     641             :     static void
     642             :     MergeFontFeatures(const gfxFontStyle *aStyle,
     643             :                       const nsTArray<gfxFontFeature>& aFontFeatures,
     644             :                       bool aDisableLigatures,
     645             :                       const nsAString& aFamilyName,
     646             :                       bool aAddSmallCaps,
     647             :                       void (*aHandleFeature)(const uint32_t&,
     648             :                                              uint32_t&, void*),
     649             :                       void* aHandleFeatureData);
     650             : 
     651             : protected:
     652             :     // the font this shaper is working with. The font owns a UniquePtr reference
     653             :     // to this object, and will destroy it before it dies. Thus, mFont will always
     654             :     // be valid.
     655             :     gfxFont* MOZ_NON_OWNING_REF mFont;
     656             : };
     657             : 
     658         352 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontShaper::RoundingFlags)
     659             : 
     660             : /*
     661             :  * gfxShapedText is an abstract superclass for gfxShapedWord and gfxTextRun.
     662             :  * These are objects that store a list of zero or more glyphs for each character.
     663             :  * For each glyph we store the glyph ID, the advance, and possibly x/y-offsets.
     664             :  * The idea is that a string is rendered by a loop that draws each glyph
     665             :  * at its designated offset from the current point, then advances the current
     666             :  * point by the glyph's advance in the direction of the textrun (LTR or RTL).
     667             :  * Each glyph advance is always rounded to the nearest appunit; this ensures
     668             :  * consistent results when dividing the text in a textrun into multiple text
     669             :  * frames (frame boundaries are always aligned to appunits). We optimize
     670             :  * for the case where a character has a single glyph and zero xoffset and yoffset,
     671             :  * and the glyph ID and advance are in a reasonable range so we can pack all
     672             :  * necessary data into 32 bits.
     673             :  *
     674             :  * gfxFontShaper can shape text into either a gfxShapedWord (cached by a gfxFont)
     675             :  * or directly into a gfxTextRun (for cases where we want to shape textruns in
     676             :  * their entirety rather than using cached words, because there may be layout
     677             :  * features that depend on the inter-word spaces).
     678             :  */
     679             : class gfxShapedText
     680             : {
     681             : public:
     682             :     typedef mozilla::unicode::Script Script;
     683             : 
     684         115 :     gfxShapedText(uint32_t aLength, mozilla::gfx::ShapedTextFlags aFlags,
     685             :                   int32_t aAppUnitsPerDevUnit)
     686         115 :         : mLength(aLength)
     687             :         , mFlags(aFlags)
     688         115 :         , mAppUnitsPerDevUnit(aAppUnitsPerDevUnit)
     689         115 :     { }
     690             : 
     691          71 :     virtual ~gfxShapedText() { }
     692             : 
     693             :     /**
     694             :      * This class records the information associated with a character in the
     695             :      * input string. It's optimized for the case where there is one glyph
     696             :      * representing that character alone.
     697             :      * 
     698             :      * A character can have zero or more associated glyphs. Each glyph
     699             :      * has an advance width and an x and y offset.
     700             :      * A character may be the start of a cluster.
     701             :      * A character may be the start of a ligature group.
     702             :      * A character can be "missing", indicating that the system is unable
     703             :      * to render the character.
     704             :      * 
     705             :      * All characters in a ligature group conceptually share all the glyphs
     706             :      * associated with the characters in a group.
     707             :      */
     708             :     class CompressedGlyph {
     709             :     public:
     710          92 :         CompressedGlyph() { mValue = 0; }
     711             : 
     712             :         enum {
     713             :             // Indicates that a cluster and ligature group starts at this
     714             :             // character; this character has a single glyph with a reasonable
     715             :             // advance and zero offsets. A "reasonable" advance
     716             :             // is one that fits in the available bits (currently 12) (specified
     717             :             // in appunits).
     718             :             FLAG_IS_SIMPLE_GLYPH  = 0x80000000U,
     719             : 
     720             :             // Indicates whether a linebreak is allowed before this character;
     721             :             // this is a two-bit field that holds a FLAG_BREAK_TYPE_xxx value
     722             :             // indicating the kind of linebreak (if any) allowed here.
     723             :             FLAGS_CAN_BREAK_BEFORE = 0x60000000U,
     724             : 
     725             :             FLAGS_CAN_BREAK_SHIFT = 29,
     726             :             FLAG_BREAK_TYPE_NONE   = 0,
     727             :             FLAG_BREAK_TYPE_NORMAL = 1,
     728             :             FLAG_BREAK_TYPE_HYPHEN = 2,
     729             : 
     730             :             FLAG_CHAR_IS_SPACE     = 0x10000000U,
     731             : 
     732             :             // The advance is stored in appunits
     733             :             ADVANCE_MASK  = 0x0FFF0000U,
     734             :             ADVANCE_SHIFT = 16,
     735             : 
     736             :             GLYPH_MASK = 0x0000FFFFU,
     737             : 
     738             :             // Non-simple glyphs may or may not have glyph data in the
     739             :             // corresponding mDetailedGlyphs entry. They have the following
     740             :             // flag bits:
     741             : 
     742             :             // When NOT set, indicates that this character corresponds to a
     743             :             // missing glyph and should be skipped (or possibly, render the character
     744             :             // Unicode value in some special way). If there are glyphs,
     745             :             // the mGlyphID is actually the UTF16 character code. The bit is
     746             :             // inverted so we can memset the array to zero to indicate all missing.
     747             :             FLAG_NOT_MISSING              = 0x01,
     748             :             FLAG_NOT_CLUSTER_START        = 0x02,
     749             :             FLAG_NOT_LIGATURE_GROUP_START = 0x04,
     750             : 
     751             :             FLAG_CHAR_IS_TAB              = 0x08,
     752             :             FLAG_CHAR_IS_NEWLINE          = 0x10,
     753             :             // Per CSS Text Decoration Module Level 3, emphasis marks are not
     754             :             // drawn for any character in Unicode categories Z*, Cc, Cf, and Cn
     755             :             // which is not combined with any combining characters. This flag is
     756             :             // set for all those characters except 0x20 whitespace.
     757             :             FLAG_CHAR_NO_EMPHASIS_MARK    = 0x20,
     758             :             CHAR_TYPE_FLAGS_MASK          = 0x38,
     759             : 
     760             :             GLYPH_COUNT_MASK = 0x00FFFF00U,
     761             :             GLYPH_COUNT_SHIFT = 8
     762             :         };
     763             : 
     764             :         // "Simple glyphs" have a simple glyph ID, simple advance and their
     765             :         // x and y offsets are zero. Also the glyph extents do not overflow
     766             :         // the font-box defined by the font ascent, descent and glyph advance width.
     767             :         // These case is optimized to avoid storing DetailedGlyphs.
     768             : 
     769             :         // Returns true if the glyph ID aGlyph fits into the compressed representation
     770         646 :         static bool IsSimpleGlyphID(uint32_t aGlyph) {
     771         646 :             return (aGlyph & GLYPH_MASK) == aGlyph;
     772             :         }
     773             :         // Returns true if the advance aAdvance fits into the compressed representation.
     774             :         // aAdvance is in appunits.
     775         646 :         static bool IsSimpleAdvance(uint32_t aAdvance) {
     776         646 :             return (aAdvance & (ADVANCE_MASK >> ADVANCE_SHIFT)) == aAdvance;
     777             :         }
     778             : 
     779        3229 :         bool IsSimpleGlyph() const { return (mValue & FLAG_IS_SIMPLE_GLYPH) != 0; }
     780        2224 :         uint32_t GetSimpleAdvance() const { return (mValue & ADVANCE_MASK) >> ADVANCE_SHIFT; }
     781        1262 :         uint32_t GetSimpleGlyph() const { return mValue & GLYPH_MASK; }
     782             : 
     783           0 :         bool IsMissing() const { return (mValue & (FLAG_NOT_MISSING|FLAG_IS_SIMPLE_GLYPH)) == 0; }
     784         271 :         bool IsClusterStart() const {
     785         271 :             return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_CLUSTER_START);
     786             :         }
     787         143 :         bool IsLigatureGroupStart() const {
     788         143 :             return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_LIGATURE_GROUP_START);
     789             :         }
     790           0 :         bool IsLigatureContinuation() const {
     791           0 :             return (mValue & FLAG_IS_SIMPLE_GLYPH) == 0 &&
     792           0 :                 (mValue & (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING)) ==
     793           0 :                     (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING);
     794             :         }
     795             : 
     796             :         // Return true if the original character was a normal (breakable,
     797             :         // trimmable) space (U+0020). Not true for other characters that
     798             :         // may happen to map to the space glyph (U+00A0).
     799         105 :         bool CharIsSpace() const {
     800         105 :             return (mValue & FLAG_CHAR_IS_SPACE) != 0;
     801             :         }
     802             : 
     803         208 :         bool CharIsTab() const {
     804         208 :             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_TAB) != 0;
     805             :         }
     806         208 :         bool CharIsNewline() const {
     807         208 :             return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_NEWLINE) != 0;
     808             :         }
     809           0 :         bool CharMayHaveEmphasisMark() const {
     810           0 :             return !CharIsSpace() &&
     811           0 :                 (IsSimpleGlyph() || !(mValue & FLAG_CHAR_NO_EMPHASIS_MARK));
     812             :         }
     813             : 
     814         325 :         uint32_t CharTypeFlags() const {
     815         325 :             return IsSimpleGlyph() ? 0 : (mValue & CHAR_TYPE_FLAGS_MASK);
     816             :         }
     817             : 
     818           0 :         void SetClusterStart(bool aIsClusterStart) {
     819           0 :             NS_ASSERTION(!IsSimpleGlyph(),
     820             :                          "can't call SetClusterStart on simple glyphs");
     821           0 :             if (aIsClusterStart) {
     822           0 :                 mValue &= ~FLAG_NOT_CLUSTER_START;
     823             :             } else {
     824           0 :                 mValue |= FLAG_NOT_CLUSTER_START;
     825             :             }
     826           0 :         }
     827             : 
     828         569 :         uint8_t CanBreakBefore() const {
     829         569 :             return (mValue & FLAGS_CAN_BREAK_BEFORE) >> FLAGS_CAN_BREAK_SHIFT;
     830             :         }
     831             :         // Returns FLAGS_CAN_BREAK_BEFORE if the setting changed, 0 otherwise
     832         154 :         uint32_t SetCanBreakBefore(uint8_t aCanBreakBefore) {
     833         154 :             NS_ASSERTION(aCanBreakBefore <= 2,
     834             :                          "Bogus break-before value!");
     835         154 :             uint32_t breakMask = (uint32_t(aCanBreakBefore) << FLAGS_CAN_BREAK_SHIFT);
     836         154 :             uint32_t toggle = breakMask ^ (mValue & FLAGS_CAN_BREAK_BEFORE);
     837         154 :             mValue ^= toggle;
     838         154 :             return toggle;
     839             :         }
     840             : 
     841         323 :         CompressedGlyph& SetSimpleGlyph(uint32_t aAdvanceAppUnits, uint32_t aGlyph) {
     842         323 :             NS_ASSERTION(IsSimpleAdvance(aAdvanceAppUnits), "Advance overflow");
     843         323 :             NS_ASSERTION(IsSimpleGlyphID(aGlyph), "Glyph overflow");
     844         323 :             NS_ASSERTION(!CharTypeFlags(), "Char type flags lost");
     845         646 :             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) |
     846         323 :                 FLAG_IS_SIMPLE_GLYPH |
     847         646 :                 (aAdvanceAppUnits << ADVANCE_SHIFT) | aGlyph;
     848         323 :             return *this;
     849             :         }
     850           2 :         CompressedGlyph& SetComplex(bool aClusterStart, bool aLigatureStart,
     851             :                 uint32_t aGlyphCount) {
     852           4 :             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) |
     853           2 :                 FLAG_NOT_MISSING |
     854           4 :                 CharTypeFlags() |
     855           2 :                 (aClusterStart ? 0 : FLAG_NOT_CLUSTER_START) |
     856           2 :                 (aLigatureStart ? 0 : FLAG_NOT_LIGATURE_GROUP_START) |
     857           2 :                 (aGlyphCount << GLYPH_COUNT_SHIFT);
     858           2 :             return *this;
     859             :         }
     860             :         /**
     861             :          * Missing glyphs are treated as ligature group starts; don't mess with
     862             :          * the cluster-start flag (see bugs 618870 and 619286).
     863             :          */
     864           0 :         CompressedGlyph& SetMissing(uint32_t aGlyphCount) {
     865           0 :             mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_NOT_CLUSTER_START |
     866           0 :                                 FLAG_CHAR_IS_SPACE)) |
     867           0 :                 CharTypeFlags() |
     868           0 :                 (aGlyphCount << GLYPH_COUNT_SHIFT);
     869           0 :             return *this;
     870             :         }
     871           0 :         uint32_t GetGlyphCount() const {
     872           0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
     873           0 :             return (mValue & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT;
     874             :         }
     875             : 
     876          58 :         void SetIsSpace() {
     877          58 :             mValue |= FLAG_CHAR_IS_SPACE;
     878          58 :         }
     879           0 :         void SetIsTab() {
     880           0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
     881           0 :             mValue |= FLAG_CHAR_IS_TAB;
     882           0 :         }
     883           0 :         void SetIsNewline() {
     884           0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
     885           0 :             mValue |= FLAG_CHAR_IS_NEWLINE;
     886           0 :         }
     887           0 :         void SetNoEmphasisMark() {
     888           0 :             NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
     889           0 :             mValue |= FLAG_CHAR_NO_EMPHASIS_MARK;
     890           0 :         }
     891             : 
     892             :     private:
     893             :         uint32_t mValue;
     894             :     };
     895             : 
     896             :     // Accessor for the array of CompressedGlyph records, which will be in
     897             :     // a different place in gfxShapedWord vs gfxTextRun
     898             :     virtual const CompressedGlyph *GetCharacterGlyphs() const = 0;
     899             :     virtual CompressedGlyph *GetCharacterGlyphs() = 0;
     900             : 
     901             :     /**
     902             :      * When the glyphs for a character don't fit into a CompressedGlyph record
     903             :      * in SimpleGlyph format, we use an array of DetailedGlyphs instead.
     904             :      */
     905             :     struct DetailedGlyph {
     906             :         /** The glyphID, or the Unicode character
     907             :          * if this is a missing glyph */
     908             :         uint32_t mGlyphID;
     909             :         /** The advance, x-offset and y-offset of the glyph, in appunits
     910             :          *  mAdvance is in the text direction (RTL or LTR)
     911             :          *  mXOffset is always from left to right
     912             :          *  mYOffset is always from top to bottom */   
     913             :         int32_t  mAdvance;
     914             :         float    mXOffset, mYOffset;
     915             :     };
     916             : 
     917             :     void SetGlyphs(uint32_t aCharIndex, CompressedGlyph aGlyph,
     918             :                    const DetailedGlyph *aGlyphs);
     919             : 
     920             :     void SetMissingGlyph(uint32_t aIndex, uint32_t aChar, gfxFont *aFont);
     921             : 
     922             :     void SetIsSpace(uint32_t aIndex) {
     923             :         GetCharacterGlyphs()[aIndex].SetIsSpace();
     924             :     }
     925             : 
     926         146 :     bool HasDetailedGlyphs() const {
     927         146 :         return mDetailedGlyphs != nullptr;
     928             :     }
     929             : 
     930             :     bool IsLigatureGroupStart(uint32_t aPos) {
     931             :         NS_ASSERTION(aPos < GetLength(), "aPos out of range");
     932             :         return GetCharacterGlyphs()[aPos].IsLigatureGroupStart();
     933             :     }
     934             : 
     935             :     // NOTE that this must not be called for a character offset that does
     936             :     // not have any DetailedGlyph records; callers must have verified that
     937             :     // GetCharacterGlyphs()[aCharIndex].GetGlyphCount() is greater than zero.
     938           0 :     DetailedGlyph *GetDetailedGlyphs(uint32_t aCharIndex) const {
     939           0 :         NS_ASSERTION(GetCharacterGlyphs() && HasDetailedGlyphs() &&
     940             :                      !GetCharacterGlyphs()[aCharIndex].IsSimpleGlyph() &&
     941             :                      GetCharacterGlyphs()[aCharIndex].GetGlyphCount() > 0,
     942             :                      "invalid use of GetDetailedGlyphs; check the caller!");
     943           0 :         return mDetailedGlyphs->Get(aCharIndex);
     944             :     }
     945             : 
     946             :     void AdjustAdvancesForSyntheticBold(float aSynBoldOffset,
     947             :                                         uint32_t aOffset, uint32_t aLength);
     948             : 
     949             :     // Mark clusters in the CompressedGlyph records, starting at aOffset,
     950             :     // based on the Unicode properties of the text in aString.
     951             :     // This is also responsible to set the IsSpace flag for space characters.
     952             :     void SetupClusterBoundaries(uint32_t         aOffset,
     953             :                                 const char16_t *aString,
     954             :                                 uint32_t         aLength);
     955             :     // In 8-bit text, there won't actually be any clusters, but we still need
     956             :     // the space-marking functionality.
     957             :     void SetupClusterBoundaries(uint32_t       aOffset,
     958             :                                 const uint8_t *aString,
     959             :                                 uint32_t       aLength);
     960             : 
     961        1071 :     mozilla::gfx::ShapedTextFlags GetFlags() const {
     962        1071 :         return mFlags;
     963             :     }
     964             : 
     965          88 :     bool IsVertical() const {
     966         176 :         return (GetFlags() & mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_MASK) !=
     967         176 :                 mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_HORIZONTAL;
     968             :     }
     969             : 
     970          48 :     bool UseCenterBaseline() const {
     971             :         mozilla::gfx::ShapedTextFlags orient =
     972          48 :             GetFlags() & mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_MASK;
     973          48 :         return orient == mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_MIXED ||
     974          48 :                orient == mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT;
     975             :     }
     976             : 
     977         235 :     bool IsRightToLeft() const {
     978         470 :         return (GetFlags() & mozilla::gfx::ShapedTextFlags::TEXT_IS_RTL) ==
     979         470 :                mozilla::gfx::ShapedTextFlags::TEXT_IS_RTL;
     980             :     }
     981             : 
     982          84 :     bool IsSidewaysLeft() const {
     983         168 :         return (GetFlags() & mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_MASK) ==
     984         168 :                mozilla::gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT;
     985             :     }
     986             : 
     987             :     // Return true if the logical inline direction is reversed compared to
     988             :     // normal physical coordinates (i.e. if it is leftwards or upwards)
     989          84 :     bool IsInlineReversed() const {
     990          84 :         return IsSidewaysLeft() != IsRightToLeft();
     991             :     }
     992             : 
     993          66 :     gfxFloat GetDirection() const {
     994          66 :         return IsInlineReversed() ? -1.0f : 1.0f;
     995             :     }
     996             : 
     997          34 :     bool DisableLigatures() const {
     998          68 :         return (GetFlags() &
     999          68 :                 mozilla::gfx::ShapedTextFlags::TEXT_DISABLE_OPTIONAL_LIGATURES) ==
    1000          68 :                mozilla::gfx::ShapedTextFlags::TEXT_DISABLE_OPTIONAL_LIGATURES;
    1001             :     }
    1002             : 
    1003         190 :     bool TextIs8Bit() const {
    1004         380 :         return (GetFlags() & mozilla::gfx::ShapedTextFlags::TEXT_IS_8BIT) ==
    1005         380 :                mozilla::gfx::ShapedTextFlags::TEXT_IS_8BIT;
    1006             :     }
    1007             : 
    1008         329 :     int32_t GetAppUnitsPerDevUnit() const {
    1009         329 :         return mAppUnitsPerDevUnit;
    1010             :     }
    1011             : 
    1012        1747 :     uint32_t GetLength() const {
    1013        1747 :         return mLength;
    1014             :     }
    1015             : 
    1016             :     bool FilterIfIgnorable(uint32_t aIndex, uint32_t aCh);
    1017             : 
    1018             : protected:
    1019             :     // Allocate aCount DetailedGlyphs for the given index
    1020             :     DetailedGlyph *AllocateDetailedGlyphs(uint32_t aCharIndex,
    1021             :                                           uint32_t aCount);
    1022             : 
    1023             :     // Ensure the glyph on the given index is complex glyph so that we can use
    1024             :     // it to record specific characters that layout may need to detect.
    1025           0 :     void EnsureComplexGlyph(uint32_t aIndex, CompressedGlyph& aGlyph)
    1026             :     {
    1027           0 :         MOZ_ASSERT(GetCharacterGlyphs() + aIndex == &aGlyph);
    1028           0 :         if (aGlyph.IsSimpleGlyph()) {
    1029             :             DetailedGlyph details = {
    1030           0 :                 aGlyph.GetSimpleGlyph(),
    1031           0 :                 (int32_t) aGlyph.GetSimpleAdvance(),
    1032             :                 0, 0
    1033           0 :             };
    1034           0 :             SetGlyphs(aIndex, CompressedGlyph().SetComplex(true, true, 1),
    1035           0 :                       &details);
    1036             :         }
    1037           0 :     }
    1038             : 
    1039             :     // For characters whose glyph data does not fit the "simple" glyph criteria
    1040             :     // in CompressedGlyph, we use a sorted array to store the association
    1041             :     // between the source character offset and an index into an array 
    1042             :     // DetailedGlyphs. The CompressedGlyph record includes a count of
    1043             :     // the number of DetailedGlyph records that belong to the character,
    1044             :     // starting at the given index.
    1045           0 :     class DetailedGlyphStore {
    1046             :     public:
    1047           0 :         DetailedGlyphStore()
    1048           0 :             : mLastUsed(0)
    1049           0 :         { }
    1050             : 
    1051             :         // This is optimized for the most common calling patterns:
    1052             :         // we rarely need random access to the records, access is most commonly
    1053             :         // sequential through the textRun, so we record the last-used index
    1054             :         // and check whether the caller wants the same record again, or the
    1055             :         // next; if not, it's most likely we're starting over from the start
    1056             :         // of the run, so we check the first entry before resorting to binary
    1057             :         // search as a last resort.
    1058             :         // NOTE that this must not be called for a character offset that does
    1059             :         // not have any DetailedGlyph records; callers must have verified that
    1060             :         // mCharacterGlyphs[aOffset].GetGlyphCount() is greater than zero
    1061             :         // before calling this, otherwise the assertions here will fire (in a
    1062             :         // debug build), and we'll probably crash.
    1063           0 :         DetailedGlyph* Get(uint32_t aOffset) {
    1064           0 :             NS_ASSERTION(mOffsetToIndex.Length() > 0,
    1065             :                          "no detailed glyph records!");
    1066           0 :             DetailedGlyph* details = mDetails.Elements();
    1067             :             // check common cases (fwd iteration, initial entry, etc) first
    1068           0 :             if (mLastUsed < mOffsetToIndex.Length() - 1 &&
    1069           0 :                 aOffset == mOffsetToIndex[mLastUsed + 1].mOffset) {
    1070           0 :                 ++mLastUsed;
    1071           0 :             } else if (aOffset == mOffsetToIndex[0].mOffset) {
    1072           0 :                 mLastUsed = 0;
    1073           0 :             } else if (aOffset == mOffsetToIndex[mLastUsed].mOffset) {
    1074             :                 // do nothing
    1075           0 :             } else if (mLastUsed > 0 &&
    1076           0 :                        aOffset == mOffsetToIndex[mLastUsed - 1].mOffset) {
    1077           0 :                 --mLastUsed;
    1078             :             } else {
    1079           0 :                 mLastUsed =
    1080           0 :                     mOffsetToIndex.BinaryIndexOf(aOffset, CompareToOffset());
    1081             :             }
    1082           0 :             NS_ASSERTION(mLastUsed != nsTArray<DGRec>::NoIndex,
    1083             :                          "detailed glyph record missing!");
    1084           0 :             return details + mOffsetToIndex[mLastUsed].mIndex;
    1085             :         }
    1086             : 
    1087           0 :         DetailedGlyph* Allocate(uint32_t aOffset, uint32_t aCount) {
    1088           0 :             uint32_t detailIndex = mDetails.Length();
    1089           0 :             DetailedGlyph *details = mDetails.AppendElements(aCount);
    1090             :             // We normally set up glyph records sequentially, so the common case
    1091             :             // here is to append new records to the mOffsetToIndex array;
    1092             :             // test for that before falling back to the InsertElementSorted
    1093             :             // method.
    1094           0 :             if (mOffsetToIndex.Length() == 0 ||
    1095           0 :                 aOffset > mOffsetToIndex[mOffsetToIndex.Length() - 1].mOffset) {
    1096           0 :                 mOffsetToIndex.AppendElement(DGRec(aOffset, detailIndex));
    1097             :             } else {
    1098           0 :                 mOffsetToIndex.InsertElementSorted(DGRec(aOffset, detailIndex),
    1099           0 :                                                    CompareRecordOffsets());
    1100             :             }
    1101           0 :             return details;
    1102             :         }
    1103             : 
    1104           0 :         size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
    1105           0 :             return aMallocSizeOf(this) +
    1106           0 :                 mDetails.ShallowSizeOfExcludingThis(aMallocSizeOf) +
    1107           0 :                 mOffsetToIndex.ShallowSizeOfExcludingThis(aMallocSizeOf);
    1108             :         }
    1109             : 
    1110             :     private:
    1111             :         struct DGRec {
    1112           0 :             DGRec(const uint32_t& aOffset, const uint32_t& aIndex)
    1113           0 :                 : mOffset(aOffset), mIndex(aIndex) { }
    1114             :             uint32_t mOffset; // source character offset in the textrun
    1115             :             uint32_t mIndex;  // index where this char's DetailedGlyphs begin
    1116             :         };
    1117             : 
    1118             :         struct CompareToOffset {
    1119           0 :             bool Equals(const DGRec& a, const uint32_t& b) const {
    1120           0 :                 return a.mOffset == b;
    1121             :             }
    1122           0 :             bool LessThan(const DGRec& a, const uint32_t& b) const {
    1123           0 :                 return a.mOffset < b;
    1124             :             }
    1125             :         };
    1126             : 
    1127             :         struct CompareRecordOffsets {
    1128           0 :             bool Equals(const DGRec& a, const DGRec& b) const {
    1129           0 :                 return a.mOffset == b.mOffset;
    1130             :             }
    1131           0 :             bool LessThan(const DGRec& a, const DGRec& b) const {
    1132           0 :                 return a.mOffset < b.mOffset;
    1133             :             }
    1134             :         };
    1135             : 
    1136             :         // Concatenated array of all the DetailedGlyph records needed for the
    1137             :         // textRun; individual character offsets are associated with indexes
    1138             :         // into this array via the mOffsetToIndex table.
    1139             :         nsTArray<DetailedGlyph>     mDetails;
    1140             : 
    1141             :         // For each character offset that needs DetailedGlyphs, we record the
    1142             :         // index in mDetails where the list of glyphs begins. This array is
    1143             :         // sorted by mOffset.
    1144             :         nsTArray<DGRec>             mOffsetToIndex;
    1145             : 
    1146             :         // Records the most recently used index into mOffsetToIndex, so that
    1147             :         // we can support sequential access more quickly than just doing
    1148             :         // a binary search each time.
    1149             :         nsTArray<DGRec>::index_type mLastUsed;
    1150             :     };
    1151             : 
    1152             :     mozilla::UniquePtr<DetailedGlyphStore>   mDetailedGlyphs;
    1153             : 
    1154             :     // Number of char16_t characters and CompressedGlyph glyph records
    1155             :     uint32_t                        mLength;
    1156             : 
    1157             :     // Shaping flags (direction, ligature-suppression)
    1158             :     mozilla::gfx::ShapedTextFlags   mFlags;
    1159             : 
    1160             :     uint16_t                        mAppUnitsPerDevUnit;
    1161             : };
    1162             : 
    1163             : /*
    1164             :  * gfxShapedWord: an individual (space-delimited) run of text shaped with a
    1165             :  * particular font, without regard to external context.
    1166             :  *
    1167             :  * The glyph data is copied into gfxTextRuns as needed from the cache of
    1168             :  * ShapedWords associated with each gfxFont instance.
    1169             :  */
    1170           0 : class gfxShapedWord final : public gfxShapedText
    1171             : {
    1172             : public:
    1173             :     typedef mozilla::unicode::Script Script;
    1174             : 
    1175             :     // Create a ShapedWord that can hold glyphs for aLength characters,
    1176             :     // with mCharacterGlyphs sized appropriately.
    1177             :     //
    1178             :     // Returns null on allocation failure (does NOT use infallible alloc)
    1179             :     // so caller must check for success.
    1180             :     //
    1181             :     // This does NOT perform shaping, so the returned word contains no
    1182             :     // glyph data; the caller must call gfxFont::ShapeText() with appropriate
    1183             :     // parameters to set up the glyphs.
    1184          30 :     static gfxShapedWord* Create(const uint8_t *aText, uint32_t aLength,
    1185             :                                  Script aRunScript,
    1186             :                                  int32_t aAppUnitsPerDevUnit,
    1187             :                                  mozilla::gfx::ShapedTextFlags aFlags,
    1188             :                                  gfxFontShaper::RoundingFlags aRounding) {
    1189          30 :         NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
    1190             :                      "excessive length for gfxShapedWord!");
    1191             : 
    1192             :         // Compute size needed including the mCharacterGlyphs array
    1193             :         // and a copy of the original text
    1194             :         uint32_t size =
    1195             :             offsetof(gfxShapedWord, mCharGlyphsStorage) +
    1196          30 :             aLength * (sizeof(CompressedGlyph) + sizeof(uint8_t));
    1197          30 :         void *storage = malloc(size);
    1198          30 :         if (!storage) {
    1199           0 :             return nullptr;
    1200             :         }
    1201             : 
    1202             :         // Construct in the pre-allocated storage, using placement new
    1203             :         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
    1204             :                                            aAppUnitsPerDevUnit, aFlags,
    1205          30 :                                            aRounding);
    1206             :     }
    1207             : 
    1208          21 :     static gfxShapedWord* Create(const char16_t *aText, uint32_t aLength,
    1209             :                                  Script aRunScript,
    1210             :                                  int32_t aAppUnitsPerDevUnit,
    1211             :                                  mozilla::gfx::ShapedTextFlags aFlags,
    1212             :                                  gfxFontShaper::RoundingFlags aRounding) {
    1213          21 :         NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
    1214             :                      "excessive length for gfxShapedWord!");
    1215             : 
    1216             :         // In the 16-bit version of Create, if the TEXT_IS_8BIT flag is set,
    1217             :         // then we convert the text to an 8-bit version and call the 8-bit
    1218             :         // Create function instead.
    1219          21 :         if (aFlags & mozilla::gfx::ShapedTextFlags::TEXT_IS_8BIT) {
    1220          38 :             nsAutoCString narrowText;
    1221          38 :             LossyAppendUTF16toASCII(nsDependentSubstring(aText, aLength),
    1222          19 :                                     narrowText);
    1223          19 :             return Create((const uint8_t*)(narrowText.BeginReading()),
    1224             :                           aLength, aRunScript, aAppUnitsPerDevUnit, aFlags,
    1225          19 :                           aRounding);
    1226             :         }
    1227             : 
    1228             :         uint32_t size =
    1229             :             offsetof(gfxShapedWord, mCharGlyphsStorage) +
    1230           2 :             aLength * (sizeof(CompressedGlyph) + sizeof(char16_t));
    1231           2 :         void *storage = malloc(size);
    1232           2 :         if (!storage) {
    1233           0 :             return nullptr;
    1234             :         }
    1235             : 
    1236             :         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
    1237             :                                            aAppUnitsPerDevUnit, aFlags,
    1238           2 :                                            aRounding);
    1239             :     }
    1240             : 
    1241             :     // Override operator delete to properly free the object that was
    1242             :     // allocated via malloc.
    1243           0 :     void operator delete(void* p) {
    1244           0 :         free(p);
    1245           0 :     }
    1246             : 
    1247           0 :     virtual const CompressedGlyph *GetCharacterGlyphs() const override {
    1248           0 :         return &mCharGlyphsStorage[0];
    1249             :     }
    1250         161 :     virtual CompressedGlyph *GetCharacterGlyphs() override {
    1251         161 :         return &mCharGlyphsStorage[0];
    1252             :     }
    1253             : 
    1254          88 :     const uint8_t* Text8Bit() const {
    1255          88 :         NS_ASSERTION(TextIs8Bit(), "invalid use of Text8Bit()");
    1256          88 :         return reinterpret_cast<const uint8_t*>(mCharGlyphsStorage + GetLength());
    1257             :     }
    1258             : 
    1259           7 :     const char16_t* TextUnicode() const {
    1260           7 :         NS_ASSERTION(!TextIs8Bit(), "invalid use of TextUnicode()");
    1261           7 :         return reinterpret_cast<const char16_t*>(mCharGlyphsStorage + GetLength());
    1262             :     }
    1263             : 
    1264             :     char16_t GetCharAt(uint32_t aOffset) const {
    1265             :         NS_ASSERTION(aOffset < GetLength(), "aOffset out of range");
    1266             :         return TextIs8Bit() ?
    1267             :             char16_t(Text8Bit()[aOffset]) : TextUnicode()[aOffset];
    1268             :     }
    1269             : 
    1270          95 :     Script GetScript() const {
    1271          95 :         return mScript;
    1272             :     }
    1273             : 
    1274          95 :     gfxFontShaper::RoundingFlags GetRounding() const {
    1275          95 :         return mRounding;
    1276             :     }
    1277             : 
    1278          95 :     void ResetAge() {
    1279          95 :         mAgeCounter = 0;
    1280          95 :     }
    1281           0 :     uint32_t IncrementAge() {
    1282           0 :         return ++mAgeCounter;
    1283             :     }
    1284             : 
    1285             :     // Helper used when hashing a word for the shaped-word caches
    1286         802 :     static uint32_t HashMix(uint32_t aHash, char16_t aCh)
    1287             :     {
    1288         802 :         return (aHash >> 28) ^ (aHash << 4) ^ aCh;
    1289             :     }
    1290             : 
    1291             : private:
    1292             :     // so that gfxTextRun can share our DetailedGlyphStore class
    1293             :     friend class gfxTextRun;
    1294             : 
    1295             :     // Construct storage for a ShapedWord, ready to receive glyph data
    1296          30 :     gfxShapedWord(const uint8_t *aText, uint32_t aLength,
    1297             :                   Script aRunScript,
    1298             :                   int32_t aAppUnitsPerDevUnit,
    1299             :                   mozilla::gfx::ShapedTextFlags aFlags,
    1300             :                   gfxFontShaper::RoundingFlags aRounding)
    1301          60 :         : gfxShapedText(aLength, aFlags | mozilla::gfx::ShapedTextFlags::TEXT_IS_8BIT,
    1302             :                         aAppUnitsPerDevUnit)
    1303             :         , mScript(aRunScript)
    1304             :         , mRounding(aRounding)
    1305          60 :         , mAgeCounter(0)
    1306             :     {
    1307          30 :         memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
    1308          30 :         uint8_t *text = reinterpret_cast<uint8_t*>(&mCharGlyphsStorage[aLength]);
    1309          30 :         memcpy(text, aText, aLength * sizeof(uint8_t));
    1310          30 :     }
    1311             : 
    1312           2 :     gfxShapedWord(const char16_t *aText, uint32_t aLength,
    1313             :                   Script aRunScript,
    1314             :                   int32_t aAppUnitsPerDevUnit,
    1315             :                   mozilla::gfx::ShapedTextFlags aFlags,
    1316             :                   gfxFontShaper::RoundingFlags aRounding)
    1317           2 :         : gfxShapedText(aLength, aFlags, aAppUnitsPerDevUnit)
    1318             :         , mScript(aRunScript)
    1319             :         , mRounding(aRounding)
    1320           2 :         , mAgeCounter(0)
    1321             :     {
    1322           2 :         memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
    1323           2 :         char16_t *text = reinterpret_cast<char16_t*>(&mCharGlyphsStorage[aLength]);
    1324           2 :         memcpy(text, aText, aLength * sizeof(char16_t));
    1325           2 :         SetupClusterBoundaries(0, aText, aLength);
    1326           2 :     }
    1327             : 
    1328             :     Script           mScript;
    1329             : 
    1330             :     gfxFontShaper::RoundingFlags mRounding;
    1331             : 
    1332             :     uint32_t         mAgeCounter;
    1333             : 
    1334             :     // The mCharGlyphsStorage array is actually a variable-size member;
    1335             :     // when the ShapedWord is created, its size will be increased as necessary
    1336             :     // to allow the proper number of glyphs to be stored.
    1337             :     // The original text, in either 8-bit or 16-bit form, will be stored
    1338             :     // immediately following the CompressedGlyphs.
    1339             :     CompressedGlyph  mCharGlyphsStorage[1];
    1340             : };
    1341             : 
    1342             : class GlyphBufferAzure;
    1343             : struct TextRunDrawParams;
    1344             : struct FontDrawParams;
    1345             : struct EmphasisMarkDrawParams;
    1346             : 
    1347             : class gfxFont {
    1348             : 
    1349             :     friend class gfxHarfBuzzShaper;
    1350             :     friend class gfxGraphiteShaper;
    1351             : 
    1352             : protected:
    1353             :     typedef mozilla::gfx::DrawTarget DrawTarget;
    1354             :     typedef mozilla::unicode::Script Script;
    1355             :     typedef mozilla::SVGContextPaint SVGContextPaint;
    1356             : 
    1357             :     typedef gfxFontShaper::RoundingFlags RoundingFlags;
    1358             : 
    1359             : public:
    1360         241 :     nsrefcnt AddRef(void) {
    1361         241 :         NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
    1362         241 :         if (mExpirationState.IsTracked()) {
    1363           8 :             gfxFontCache::GetCache()->RemoveObject(this);
    1364             :         }
    1365         241 :         ++mRefCnt;
    1366         241 :         NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this));
    1367         241 :         return mRefCnt;
    1368             :     }
    1369         231 :     nsrefcnt Release(void) {
    1370         231 :         NS_PRECONDITION(0 != mRefCnt, "dup release");
    1371         231 :         --mRefCnt;
    1372         231 :         NS_LOG_RELEASE(this, mRefCnt, "gfxFont");
    1373         231 :         if (mRefCnt == 0) {
    1374          12 :             NotifyReleased();
    1375             :             // |this| may have been deleted.
    1376          12 :             return 0;
    1377             :         }
    1378         219 :         return mRefCnt;
    1379             :     }
    1380             : 
    1381           0 :     int32_t GetRefCount() { return mRefCnt; }
    1382             : 
    1383             :     // options to specify the kind of AA to be used when creating a font
    1384             :     typedef enum {
    1385             :         kAntialiasDefault,
    1386             :         kAntialiasNone,
    1387             :         kAntialiasGrayscale,
    1388             :         kAntialiasSubpixel
    1389             :     } AntialiasOption;
    1390             : 
    1391             : protected:
    1392             :     nsAutoRefCnt mRefCnt;
    1393             :     cairo_scaled_font_t *mScaledFont;
    1394             : 
    1395          12 :     void NotifyReleased() {
    1396          12 :         gfxFontCache *cache = gfxFontCache::GetCache();
    1397          12 :         if (cache) {
    1398             :             // Don't delete just yet; return the object to the cache for
    1399             :             // possibly recycling within some time limit
    1400          12 :             cache->NotifyReleased(this);
    1401             :         } else {
    1402             :             // The cache may have already been shut down.
    1403           0 :             delete this;
    1404             :         }
    1405          12 :     }
    1406             : 
    1407             :     gfxFont(const RefPtr<mozilla::gfx::UnscaledFont>& aUnscaledFont,
    1408             :             gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
    1409             :             AntialiasOption anAAOption = kAntialiasDefault,
    1410             :             cairo_scaled_font_t *aScaledFont = nullptr);
    1411             : 
    1412             : public:
    1413             :     virtual ~gfxFont();
    1414             : 
    1415          14 :     bool Valid() const {
    1416          14 :         return mIsValid;
    1417             :     }
    1418             : 
    1419             :     // options for the kind of bounding box to return from measurement
    1420             :     typedef enum {
    1421             :         LOOSE_INK_EXTENTS,
    1422             :             // A box that encloses all the painted pixels, and may
    1423             :             // include sidebearings and/or additional ascent/descent
    1424             :             // within the glyph cell even if the ink is smaller.
    1425             :         TIGHT_INK_EXTENTS,
    1426             :             // A box that tightly encloses all the painted pixels
    1427             :             // (although actually on Windows, at least, it may be
    1428             :             // slightly larger than strictly necessary because
    1429             :             // we can't get precise extents with ClearType).
    1430             :         TIGHT_HINTED_OUTLINE_EXTENTS
    1431             :             // A box that tightly encloses the glyph outline,
    1432             :             // ignoring possible antialiasing pixels that extend
    1433             :             // beyond this.
    1434             :             // NOTE: The default implementation of gfxFont::Measure(),
    1435             :             // which works with the glyph extents cache, does not
    1436             :             // differentiate between this and TIGHT_INK_EXTENTS.
    1437             :             // Whether the distinction is important depends on the
    1438             :             // antialiasing behavior of the platform; currently the
    1439             :             // distinction is only implemented in the gfxWindowsFont
    1440             :             // subclass, because of ClearType's tendency to paint
    1441             :             // outside the hinted outline.
    1442             :             // Also NOTE: it is relatively expensive to request this,
    1443             :             // as it does not use cached glyph extents in the font.
    1444             :     } BoundingBoxType;
    1445             : 
    1446           0 :     const nsString& GetName() const { return mFontEntry->Name(); }
    1447         127 :     const gfxFontStyle *GetStyle() const { return &mStyle; }
    1448             : 
    1449          21 :     virtual cairo_scaled_font_t* GetCairoScaledFont() { return mScaledFont; }
    1450             : 
    1451             :     virtual mozilla::UniquePtr<gfxFont>
    1452           0 :     CopyWithAntialiasOption(AntialiasOption anAAOption) {
    1453             :         // platforms where this actually matters should override
    1454           0 :         return nullptr;
    1455             :     }
    1456             : 
    1457          29 :     gfxFloat GetAdjustedSize() const {
    1458          29 :         return mAdjustedSize > 0.0
    1459          29 :                  ? mAdjustedSize
    1460          29 :                  : (mStyle.sizeAdjust == 0.0 ? 0.0 : mStyle.size);
    1461             :     }
    1462             : 
    1463           0 :     float FUnitsToDevUnitsFactor() const {
    1464             :         // check this was set up during font initialization
    1465           0 :         NS_ASSERTION(mFUnitsConvFactor >= 0.0f, "mFUnitsConvFactor not valid");
    1466           0 :         return mFUnitsConvFactor;
    1467             :     }
    1468             : 
    1469             :     // check whether this is an sfnt we can potentially use with harfbuzz
    1470             :     bool FontCanSupportHarfBuzz() {
    1471             :         return mFontEntry->HasCmapTable();
    1472             :     }
    1473             : 
    1474             :     // check whether this is an sfnt we can potentially use with Graphite
    1475         105 :     bool FontCanSupportGraphite() {
    1476         105 :         return mFontEntry->HasGraphiteTables();
    1477             :     }
    1478             : 
    1479             :     // Whether this is a font that may be doing full-color rendering,
    1480             :     // and therefore needs us to use a mask for text-shadow even when
    1481             :     // we're not actually blurring.
    1482           0 :     bool AlwaysNeedsMaskForShadow() {
    1483           0 :         return mFontEntry->TryGetColorGlyphs() ||
    1484           0 :                mFontEntry->TryGetSVGData(this) ||
    1485           0 :                mFontEntry->HasFontTable(TRUETYPE_TAG('C','B','D','T')) ||
    1486           0 :                mFontEntry->HasFontTable(TRUETYPE_TAG('s','b','i','x'));
    1487             :     }
    1488             : 
    1489             :     // whether a feature is supported by the font (limited to a small set
    1490             :     // of features for which some form of fallback needs to be implemented)
    1491             :     bool SupportsFeature(Script aScript, uint32_t aFeatureTag);
    1492             : 
    1493             :     // whether the font supports "real" small caps, petite caps etc.
    1494             :     // aFallbackToSmallCaps true when petite caps should fallback to small caps
    1495             :     bool SupportsVariantCaps(Script aScript, uint32_t aVariantCaps,
    1496             :                              bool& aFallbackToSmallCaps,
    1497             :                              bool& aSyntheticLowerToSmallCaps,
    1498             :                              bool& aSyntheticUpperToSmallCaps);
    1499             : 
    1500             :     // whether the font supports subscript/superscript feature
    1501             :     // for fallback, need to verify that all characters in the run
    1502             :     // have variant substitutions
    1503             :     bool SupportsSubSuperscript(uint32_t aSubSuperscript,
    1504             :                                 const uint8_t *aString,
    1505             :                                 uint32_t aLength,
    1506             :                                 Script aRunScript);
    1507             : 
    1508             :     bool SupportsSubSuperscript(uint32_t aSubSuperscript,
    1509             :                                 const char16_t *aString,
    1510             :                                 uint32_t aLength,
    1511             :                                 Script aRunScript);
    1512             : 
    1513             :     // Subclasses may choose to look up glyph ids for characters.
    1514             :     // If they do not override this, gfxHarfBuzzShaper will fetch the cmap
    1515             :     // table and use that.
    1516           0 :     virtual bool ProvidesGetGlyph() const {
    1517           0 :         return false;
    1518             :     }
    1519             :     // Map unicode character to glyph ID.
    1520             :     // Only used if ProvidesGetGlyph() returns true.
    1521           0 :     virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector) {
    1522           0 :         return 0;
    1523             :     }
    1524             :     // Return the horizontal advance of a glyph.
    1525             :     gfxFloat GetGlyphHAdvance(DrawTarget* aDrawTarget, uint16_t aGID);
    1526             : 
    1527             :     // Return Azure GlyphRenderingOptions for drawing this font.
    1528             :     virtual already_AddRefed<mozilla::gfx::GlyphRenderingOptions>
    1529          21 :       GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr)
    1530          21 :     { return nullptr; }
    1531             : 
    1532             :     gfxFloat SynthesizeSpaceWidth(uint32_t aCh);
    1533             : 
    1534             :     // Work out whether cairo will snap inter-glyph spacing to pixels
    1535             :     // when rendering to the given drawTarget.
    1536             :     RoundingFlags GetRoundOffsetsToPixels(DrawTarget* aDrawTarget);
    1537             : 
    1538             :     // Font metrics
    1539             :     struct Metrics {
    1540             :         gfxFloat capHeight;
    1541             :         gfxFloat xHeight;
    1542             :         gfxFloat strikeoutSize;
    1543             :         gfxFloat strikeoutOffset;
    1544             :         gfxFloat underlineSize;
    1545             :         gfxFloat underlineOffset;
    1546             : 
    1547             :         gfxFloat internalLeading;
    1548             :         gfxFloat externalLeading;
    1549             : 
    1550             :         gfxFloat emHeight;
    1551             :         gfxFloat emAscent;
    1552             :         gfxFloat emDescent;
    1553             :         gfxFloat maxHeight;
    1554             :         gfxFloat maxAscent;
    1555             :         gfxFloat maxDescent;
    1556             :         gfxFloat maxAdvance;
    1557             : 
    1558             :         gfxFloat aveCharWidth;
    1559             :         gfxFloat spaceWidth;
    1560             :         gfxFloat zeroOrAveCharWidth;  // width of '0', or if there is
    1561             :                                       // no '0' glyph in this font,
    1562             :                                       // equal to .aveCharWidth
    1563             :     };
    1564             : 
    1565             :     enum Orientation {
    1566             :         eHorizontal,
    1567             :         eVertical
    1568             :     };
    1569             : 
    1570        1111 :     const Metrics& GetMetrics(Orientation aOrientation)
    1571             :     {
    1572        1111 :         if (aOrientation == eHorizontal) {
    1573        1111 :             return GetHorizontalMetrics();
    1574             :         }
    1575           0 :         if (!mVerticalMetrics) {
    1576           0 :             mVerticalMetrics = CreateVerticalMetrics();
    1577             :         }
    1578           0 :         return *mVerticalMetrics;
    1579             :     }
    1580             : 
    1581             :     /**
    1582             :      * We let layout specify spacing on either side of any
    1583             :      * character. We need to specify both before and after
    1584             :      * spacing so that substring measurement can do the right things.
    1585             :      * These values are in appunits. They're always an integral number of
    1586             :      * appunits, but we specify them in floats in case very large spacing
    1587             :      * values are required.
    1588             :      */
    1589             :     struct Spacing {
    1590             :         gfxFloat mBefore;
    1591             :         gfxFloat mAfter;
    1592             :     };
    1593             :     /**
    1594             :      * Metrics for a particular string
    1595             :      */
    1596             :     struct RunMetrics {
    1597         120 :         RunMetrics() {
    1598         120 :             mAdvanceWidth = mAscent = mDescent = 0.0;
    1599         120 :         }
    1600             : 
    1601             :         void CombineWith(const RunMetrics& aOther, bool aOtherIsOnLeft);
    1602             : 
    1603             :         // can be negative (partly due to negative spacing).
    1604             :         // Advance widths should be additive: the advance width of the
    1605             :         // (offset1, length1) plus the advance width of (offset1 + length1,
    1606             :         // length2) should be the advance width of (offset1, length1 + length2)
    1607             :         gfxFloat mAdvanceWidth;
    1608             :         
    1609             :         // For zero-width substrings, these must be zero!
    1610             :         gfxFloat mAscent;  // always non-negative
    1611             :         gfxFloat mDescent; // always non-negative
    1612             :         
    1613             :         // Bounding box that is guaranteed to include everything drawn.
    1614             :         // If a tight boundingBox was requested when these metrics were
    1615             :         // generated, this will tightly wrap the glyphs, otherwise it is
    1616             :         // "loose" and may be larger than the true bounding box.
    1617             :         // Coordinates are relative to the baseline left origin, so typically
    1618             :         // mBoundingBox.y == -mAscent
    1619             :         gfxRect  mBoundingBox;
    1620             :     };
    1621             : 
    1622             :     /**
    1623             :      * Draw a series of glyphs to aContext. The direction of aTextRun must
    1624             :      * be honoured.
    1625             :      * @param aStart the first character to draw
    1626             :      * @param aEnd draw characters up to here
    1627             :      * @param aPt the baseline origin; the left end of the baseline
    1628             :      * for LTR textruns, the right end for RTL textruns.
    1629             :      * On return, this will be updated to the other end of the baseline.
    1630             :      * In application units, really!
    1631             :      * @param aRunParams record with drawing parameters, see TextRunDrawParams.
    1632             :      * Particular fields of interest include
    1633             :      * .spacing  spacing to insert before and after characters (for RTL
    1634             :      *   glyphs, before-spacing is inserted to the right of characters). There
    1635             :      *   are aEnd - aStart elements in this array, unless it's null to indicate
    1636             :      *   that there is no spacing.
    1637             :      * .drawMode  specifies whether the fill or stroke of the glyph should be
    1638             :      *   drawn, or if it should be drawn into the current path
    1639             :      * .contextPaint  information about how to construct the fill and
    1640             :      *   stroke pattern. Can be nullptr if we are not stroking the text, which
    1641             :      *   indicates that the current source from context should be used for fill
    1642             :      * .context  the Thebes graphics context to which we're drawing
    1643             :      * .dt  Moz2D DrawTarget to which we're drawing
    1644             :      *
    1645             :      * Callers guarantee:
    1646             :      * -- aStart and aEnd are aligned to cluster and ligature boundaries
    1647             :      * -- all glyphs use this font
    1648             :      */
    1649             :     void Draw(const gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
    1650             :               gfxPoint *aPt, const TextRunDrawParams& aRunParams,
    1651             :               mozilla::gfx::ShapedTextFlags aOrientation);
    1652             : 
    1653             :     /**
    1654             :      * Draw the emphasis marks for the given text run. Its prerequisite
    1655             :      * and output are similiar to the method Draw().
    1656             :      * @param aPt the baseline origin of the emphasis marks.
    1657             :      * @param aParams some drawing parameters, see EmphasisMarkDrawParams.
    1658             :      */
    1659             :     void DrawEmphasisMarks(const gfxTextRun* aShapedText, gfxPoint* aPt,
    1660             :                            uint32_t aOffset, uint32_t aCount,
    1661             :                            const EmphasisMarkDrawParams& aParams);
    1662             : 
    1663             :     /**
    1664             :      * Measure a run of characters. See gfxTextRun::Metrics.
    1665             :      * @param aTight if false, then return the union of the glyph extents
    1666             :      * with the font-box for the characters (the rectangle with x=0,width=
    1667             :      * the advance width for the character run,y=-(font ascent), and height=
    1668             :      * font ascent + font descent). Otherwise, we must return as tight as possible
    1669             :      * an approximation to the area actually painted by glyphs.
    1670             :      * @param aDrawTargetForTightBoundingBox when aTight is true, this must
    1671             :      * be non-null.
    1672             :      * @param aSpacing spacing to insert before and after glyphs. The bounding box
    1673             :      * need not include the spacing itself, but the spacing affects the glyph
    1674             :      * positions. null if there is no spacing.
    1675             :      * 
    1676             :      * Callers guarantee:
    1677             :      * -- aStart and aEnd are aligned to cluster and ligature boundaries
    1678             :      * -- all glyphs use this font
    1679             :      * 
    1680             :      * The default implementation just uses font metrics and aTextRun's
    1681             :      * advances, and assumes no characters fall outside the font box. In
    1682             :      * general this is insufficient, because that assumption is not always true.
    1683             :      */
    1684             :     virtual RunMetrics Measure(const gfxTextRun *aTextRun,
    1685             :                                uint32_t aStart, uint32_t aEnd,
    1686             :                                BoundingBoxType aBoundingBoxType,
    1687             :                                DrawTarget* aDrawTargetForTightBoundingBox,
    1688             :                                Spacing *aSpacing,
    1689             :                                mozilla::gfx::ShapedTextFlags aOrientation);
    1690             :     /**
    1691             :      * Line breaks have been changed at the beginning and/or end of a substring
    1692             :      * of the text. Reshaping may be required; glyph updating is permitted.
    1693             :      * @return true if anything was changed, false otherwise
    1694             :      */
    1695             :     bool NotifyLineBreaksChanged(gfxTextRun *aTextRun,
    1696             :                                    uint32_t aStart, uint32_t aLength)
    1697             :     { return false; }
    1698             : 
    1699             :     // Expiration tracking
    1700          28 :     nsExpirationState *GetExpirationState() { return &mExpirationState; }
    1701             : 
    1702             :     // Get the glyphID of a space
    1703             :     virtual uint32_t GetSpaceGlyph() = 0;
    1704             : 
    1705             :     gfxGlyphExtents *GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit);
    1706             : 
    1707             :     // You need to call SetupCairoFont on aDrawTarget just before calling this.
    1708             :     void SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID,
    1709             :                            bool aNeedTight, gfxGlyphExtents *aExtents);
    1710             : 
    1711             :     // This is called by the default Draw() implementation above.
    1712             :     virtual bool SetupCairoFont(DrawTarget* aDrawTarget) = 0;
    1713             : 
    1714          21 :     virtual bool AllowSubpixelAA() { return true; }
    1715             : 
    1716          63 :     bool IsSyntheticBold() { return mApplySyntheticBold; }
    1717             : 
    1718             :     // Amount by which synthetic bold "fattens" the glyphs:
    1719             :     // For size S up to a threshold size T, we use (0.25 + 3S / 4T),
    1720             :     // so that the result ranges from 0.25 to 1.0; thereafter,
    1721             :     // simply use (S / T).
    1722           0 :     gfxFloat GetSyntheticBoldOffset() {
    1723           0 :         gfxFloat size = GetAdjustedSize();
    1724           0 :         const gfxFloat threshold = 48.0;
    1725           0 :         return size < threshold ? (0.25 + 0.75 * size / threshold) :
    1726           0 :                                   (size / threshold);
    1727             :     }
    1728             : 
    1729         204 :     gfxFontEntry *GetFontEntry() const { return mFontEntry.get(); }
    1730         860 :     bool HasCharacter(uint32_t ch) {
    1731        1720 :         if (!mIsValid ||
    1732         860 :             (mUnicodeRangeMap && !mUnicodeRangeMap->test(ch))) {
    1733           0 :             return false;
    1734             :         }
    1735         860 :         return mFontEntry->HasCharacter(ch); 
    1736             :     }
    1737             : 
    1738          17 :     const gfxCharacterMap* GetUnicodeRangeMap() const {
    1739          17 :         return mUnicodeRangeMap.get();
    1740             :     }
    1741             : 
    1742           8 :     void SetUnicodeRangeMap(gfxCharacterMap* aUnicodeRangeMap) {
    1743           8 :         mUnicodeRangeMap = aUnicodeRangeMap;
    1744           8 :     }
    1745             : 
    1746             :     uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS) {
    1747             :         if (!mIsValid) {
    1748             :             return 0;
    1749             :         }
    1750             :         return mFontEntry->GetUVSGlyph(aCh, aVS); 
    1751             :     }
    1752             : 
    1753             :     template<typename T>
    1754             :     bool InitFakeSmallCapsRun(DrawTarget *aDrawTarget,
    1755             :                               gfxTextRun *aTextRun,
    1756             :                               const T    *aText,
    1757             :                               uint32_t    aOffset,
    1758             :                               uint32_t    aLength,
    1759             :                               uint8_t     aMatchType,
    1760             :                               mozilla::gfx::ShapedTextFlags aOrientation,
    1761             :                               Script      aScript,
    1762             :                               bool        aSyntheticLower,
    1763             :                               bool        aSyntheticUpper);
    1764             : 
    1765             :     // call the (virtual) InitTextRun method to do glyph generation/shaping,
    1766             :     // limiting the length of text passed by processing the run in multiple
    1767             :     // segments if necessary
    1768             :     template<typename T>
    1769             :     bool SplitAndInitTextRun(DrawTarget *aDrawTarget,
    1770             :                              gfxTextRun *aTextRun,
    1771             :                              const T *aString,
    1772             :                              uint32_t aRunStart,
    1773             :                              uint32_t aRunLength,
    1774             :                              Script aRunScript,
    1775             :                              bool aVertical);
    1776             : 
    1777             :     // Get a ShapedWord representing the given text (either 8- or 16-bit)
    1778             :     // for use in setting up a gfxTextRun.
    1779             :     template<typename T>
    1780             :     gfxShapedWord* GetShapedWord(DrawTarget *aDrawTarget,
    1781             :                                  const T *aText,
    1782             :                                  uint32_t aLength,
    1783             :                                  uint32_t aHash,
    1784             :                                  Script aRunScript,
    1785             :                                  bool aVertical,
    1786             :                                  int32_t aAppUnitsPerDevUnit,
    1787             :                                  mozilla::gfx::ShapedTextFlags aFlags,
    1788             :                                  RoundingFlags aRounding,
    1789             :                                  gfxTextPerfMetrics *aTextPerf);
    1790             : 
    1791             :     // Ensure the ShapedWord cache is initialized. This MUST be called before
    1792             :     // any attempt to use GetShapedWord().
    1793          71 :     void InitWordCache() {
    1794          71 :         if (!mWordCache) {
    1795           2 :             mWordCache = mozilla::MakeUnique<nsTHashtable<CacheHashEntry>>();
    1796             :         }
    1797          71 :     }
    1798             : 
    1799             :     // Called by the gfxFontCache timer to increment the age of all the words,
    1800             :     // so that they'll expire after a sufficient period of non-use
    1801             :     void AgeCachedWords();
    1802             : 
    1803             :     // Discard all cached word records; called on memory-pressure notification.
    1804           0 :     void ClearCachedWords() {
    1805           0 :         if (mWordCache) {
    1806           0 :             mWordCache->Clear();
    1807             :         }
    1808           0 :     }
    1809             : 
    1810             :     // Glyph rendering/geometry has changed, so invalidate data as necessary.
    1811             :     void NotifyGlyphsChanged();
    1812             : 
    1813             :     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    1814             :                                         FontCacheSizes* aSizes) const;
    1815             :     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    1816             :                                         FontCacheSizes* aSizes) const;
    1817             : 
    1818             :     typedef enum {
    1819             :         FONT_TYPE_DWRITE,
    1820             :         FONT_TYPE_GDI,
    1821             :         FONT_TYPE_FT2,
    1822             :         FONT_TYPE_MAC,
    1823             :         FONT_TYPE_OS2,
    1824             :         FONT_TYPE_CAIRO,
    1825             :         FONT_TYPE_FONTCONFIG
    1826             :     } FontType;
    1827             : 
    1828             :     virtual FontType GetType() const = 0;
    1829             : 
    1830          21 :     const RefPtr<mozilla::gfx::UnscaledFont>& GetUnscaledFont() const {
    1831          21 :         return mUnscaledFont;
    1832             :     }
    1833             : 
    1834          21 :     virtual already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(DrawTarget* aTarget)
    1835             :     {
    1836          21 :         return gfxPlatform::GetPlatform()->GetScaledFontForFont(aTarget, this);
    1837             :     }
    1838             : 
    1839             :     bool KerningDisabled() {
    1840             :         return mKerningSet && !mKerningEnabled;
    1841             :     }
    1842             : 
    1843             :     /**
    1844             :      * Subclass this object to be notified of glyph changes. Delete the object
    1845             :      * when no longer needed.
    1846             :      */
    1847             :     class GlyphChangeObserver {
    1848             :     public:
    1849           0 :         virtual ~GlyphChangeObserver()
    1850           0 :         {
    1851           0 :             if (mFont) {
    1852           0 :                 mFont->RemoveGlyphChangeObserver(this);
    1853             :             }
    1854           0 :         }
    1855             :         // This gets called when the gfxFont dies.
    1856           0 :         void ForgetFont() { mFont = nullptr; }
    1857             :         virtual void NotifyGlyphsChanged() = 0;
    1858             :     protected:
    1859           0 :         explicit GlyphChangeObserver(gfxFont *aFont) : mFont(aFont)
    1860             :         {
    1861           0 :             mFont->AddGlyphChangeObserver(this);
    1862           0 :         }
    1863             :         // This pointer is nulled by ForgetFont in the gfxFont's
    1864             :         // destructor. Before the gfxFont dies.
    1865             :         gfxFont* MOZ_NON_OWNING_REF mFont;
    1866             :     };
    1867             :     friend class GlyphChangeObserver;
    1868             : 
    1869           9 :     bool GlyphsMayChange()
    1870             :     {
    1871             :         // Currently only fonts with SVG glyphs can have animated glyphs
    1872           9 :         return mFontEntry->TryGetSVGData(this);
    1873             :     }
    1874             : 
    1875           0 :     static void DestroySingletons() {
    1876           0 :         delete sScriptTagToCode;
    1877           0 :         delete sDefaultFeatures;
    1878           0 :     }
    1879             : 
    1880             :     // Call TryGetMathTable() to try and load the Open Type MATH table.
    1881             :     // If (and ONLY if) TryGetMathTable() has returned true, the MathTable()
    1882             :     // method may be called to access the gfxMathTable data.
    1883             :     bool          TryGetMathTable();
    1884           0 :     gfxMathTable* MathTable() {
    1885           0 :         MOZ_RELEASE_ASSERT(mMathTable, "A successful call to TryGetMathTable() must be performed before calling this function");
    1886           0 :         return mMathTable.get();
    1887             :     }
    1888             : 
    1889             :     // Return a cloned font resized and offset to simulate sub/superscript
    1890             :     // glyphs. This does not add a reference to the returned font.
    1891             :     gfxFont* GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel);
    1892             : 
    1893             :     /**
    1894             :      * Return the reference cairo_t object from aDT.
    1895             :      */
    1896             :     static cairo_t* RefCairo(mozilla::gfx::DrawTarget* aDT);
    1897             : 
    1898             : protected:
    1899             :     virtual const Metrics& GetHorizontalMetrics() = 0;
    1900             : 
    1901             :     mozilla::UniquePtr<const Metrics> CreateVerticalMetrics();
    1902             : 
    1903             :     // Output a single glyph at *aPt, which is updated by the glyph's advance.
    1904             :     // Normal glyphs are simply accumulated in aBuffer until it is full and
    1905             :     // gets flushed, but SVG or color-font glyphs will instead be rendered
    1906             :     // directly to the destination (found from the buffer's parameters).
    1907             :     void DrawOneGlyph(uint32_t           aGlyphID,
    1908             :                       double             aAdvance,
    1909             :                       gfxPoint          *aPt,
    1910             :                       GlyphBufferAzure&  aBuffer,
    1911             :                       bool              *aEmittedGlyphs) const;
    1912             : 
    1913             :     // Output a run of glyphs at *aPt, which is updated to follow the last glyph
    1914             :     // in the run. This method also takes account of any letter-spacing provided
    1915             :     // in aRunParams.
    1916             :     bool DrawGlyphs(const gfxShapedText      *aShapedText,
    1917             :                     uint32_t                  aOffset, // offset in the textrun
    1918             :                     uint32_t                  aCount, // length of run to draw
    1919             :                     gfxPoint                 *aPt,
    1920             :                     const TextRunDrawParams&  aRunParams,
    1921             :                     const FontDrawParams&     aFontParams);
    1922             : 
    1923             :     // set the font size and offset used for
    1924             :     // synthetic subscript/superscript glyphs
    1925             :     void CalculateSubSuperSizeAndOffset(int32_t aAppUnitsPerDevPixel,
    1926             :                                         gfxFloat& aSubSuperSizeRatio,
    1927             :                                         float& aBaselineOffset);
    1928             : 
    1929             :     // Return a font that is a "clone" of this one, but reduced to 80% size
    1930             :     // (and with variantCaps set to normal). This does not add a reference to
    1931             :     // the returned font.
    1932             :     gfxFont* GetSmallCapsFont();
    1933             : 
    1934             :     // subclasses may provide (possibly hinted) glyph widths (in font units);
    1935             :     // if they do not override this, harfbuzz will use unhinted widths
    1936             :     // derived from the font tables
    1937           0 :     virtual bool ProvidesGlyphWidths() const {
    1938           0 :         return false;
    1939             :     }
    1940             : 
    1941             :     // The return value is interpreted as a horizontal advance in 16.16 fixed
    1942             :     // point format.
    1943           0 :     virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) {
    1944           0 :         return -1;
    1945             :     }
    1946             : 
    1947             :     bool IsSpaceGlyphInvisible(DrawTarget* aRefDrawTarget,
    1948             :                                const gfxTextRun* aTextRun);
    1949             : 
    1950             :     void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
    1951             :     void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
    1952             : 
    1953             :     // whether font contains substitution lookups containing spaces
    1954             :     bool HasSubstitutionRulesWithSpaceLookups(Script aRunScript);
    1955             : 
    1956             :     // do spaces participate in shaping rules? if so, can't used word cache
    1957             :     bool SpaceMayParticipateInShaping(Script aRunScript);
    1958             : 
    1959             :     // For 8-bit text, expand to 16-bit and then call the following method.
    1960             :     bool ShapeText(DrawTarget    *aContext,
    1961             :                    const uint8_t *aText,
    1962             :                    uint32_t       aOffset, // dest offset in gfxShapedText
    1963             :                    uint32_t       aLength,
    1964             :                    Script         aScript,
    1965             :                    bool           aVertical,
    1966             :                    RoundingFlags  aRounding,
    1967             :                    gfxShapedText *aShapedText); // where to store the result
    1968             : 
    1969             :     // Call the appropriate shaper to generate glyphs for aText and store
    1970             :     // them into aShapedText.
    1971             :     virtual bool ShapeText(DrawTarget      *aContext,
    1972             :                            const char16_t *aText,
    1973             :                            uint32_t         aOffset,
    1974             :                            uint32_t         aLength,
    1975             :                            Script           aScript,
    1976             :                            bool             aVertical,
    1977             :                            RoundingFlags    aRounding,
    1978             :                            gfxShapedText   *aShapedText);
    1979             : 
    1980             :     // Helper to adjust for synthetic bold and set character-type flags
    1981             :     // in the shaped text; implementations of ShapeText should call this
    1982             :     // after glyph shaping has been completed.
    1983             :     void PostShapingFixup(DrawTarget*     aContext,
    1984             :                           const char16_t* aText,
    1985             :                           uint32_t        aOffset, // position within aShapedText
    1986             :                           uint32_t        aLength,
    1987             :                           bool            aVertical,
    1988             :                           gfxShapedText*  aShapedText);
    1989             : 
    1990             :     // Shape text directly into a range within a textrun, without using the
    1991             :     // font's word cache. Intended for use when the font has layout features
    1992             :     // that involve space, and therefore require shaping complete runs rather
    1993             :     // than isolated words, or for long strings that are inefficient to cache.
    1994             :     // This will split the text on "invalid" characters (tab/newline) that are
    1995             :     // not handled via normal shaping, but does not otherwise divide up the
    1996             :     // text.
    1997             :     template<typename T>
    1998             :     bool ShapeTextWithoutWordCache(DrawTarget *aDrawTarget,
    1999             :                                    const T    *aText,
    2000             :                                    uint32_t    aOffset,
    2001             :                                    uint32_t    aLength,
    2002             :                                    Script      aScript,
    2003             :                                    bool        aVertical,
    2004             :                                    RoundingFlags aRounding,
    2005             :                                    gfxTextRun *aTextRun);
    2006             : 
    2007             :     // Shape a fragment of text (a run that is known to contain only
    2008             :     // "valid" characters, no newlines/tabs/other control chars).
    2009             :     // All non-wordcache shaping goes through here; this is the function
    2010             :     // that will ensure we don't pass excessively long runs to the various
    2011             :     // platform shapers.
    2012             :     template<typename T>
    2013             :     bool ShapeFragmentWithoutWordCache(DrawTarget *aDrawTarget,
    2014             :                                        const T    *aText,
    2015             :                                        uint32_t    aOffset,
    2016             :                                        uint32_t    aLength,
    2017             :                                        Script      aScript,
    2018             :                                        bool        aVertical,
    2019             :                                        RoundingFlags aRounding,
    2020             :                                        gfxTextRun *aTextRun);
    2021             : 
    2022             :     void CheckForFeaturesInvolvingSpace();
    2023             : 
    2024             :     // whether a given feature is included in feature settings from both the
    2025             :     // font and the style. aFeatureOn set if resolved feature value is non-zero
    2026             :     bool HasFeatureSet(uint32_t aFeature, bool& aFeatureOn);
    2027             : 
    2028             :     // used when analyzing whether a font has space contextual lookups
    2029             :     static nsDataHashtable<nsUint32HashKey,Script> *sScriptTagToCode;
    2030             :     static nsTHashtable<nsUint32HashKey>           *sDefaultFeatures;
    2031             : 
    2032             :     RefPtr<gfxFontEntry> mFontEntry;
    2033             : 
    2034             :     struct CacheHashKey {
    2035             :         union {
    2036             :             const uint8_t   *mSingle;
    2037             :             const char16_t *mDouble;
    2038             :         }                mText;
    2039             :         uint32_t         mLength;
    2040             :         mozilla::gfx::ShapedTextFlags mFlags;
    2041             :         Script           mScript;
    2042             :         int32_t          mAppUnitsPerDevUnit;
    2043             :         PLDHashNumber    mHashKey;
    2044             :         bool             mTextIs8Bit;
    2045             :         RoundingFlags    mRounding;
    2046             : 
    2047          19 :         CacheHashKey(const uint8_t *aText, uint32_t aLength,
    2048             :                      uint32_t aStringHash,
    2049             :                      Script aScriptCode, int32_t aAppUnitsPerDevUnit,
    2050             :                      mozilla::gfx::ShapedTextFlags aFlags,
    2051             :                      RoundingFlags aRounding)
    2052          19 :             : mLength(aLength),
    2053             :               mFlags(aFlags),
    2054             :               mScript(aScriptCode),
    2055             :               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
    2056             :               mHashKey(aStringHash
    2057          19 :                            + static_cast<int32_t>(aScriptCode)
    2058          19 :                            + aAppUnitsPerDevUnit * 0x100
    2059          38 :                            + uint16_t(aFlags) * 0x10000
    2060          19 :                            + int(aRounding)),
    2061             :               mTextIs8Bit(true),
    2062          38 :               mRounding(aRounding)
    2063             :         {
    2064          19 :             NS_ASSERTION(aFlags & mozilla::gfx::ShapedTextFlags::TEXT_IS_8BIT,
    2065             :                          "8-bit flag should have been set");
    2066          19 :             mText.mSingle = aText;
    2067          19 :         }
    2068             : 
    2069         108 :         CacheHashKey(const char16_t *aText, uint32_t aLength,
    2070             :                      uint32_t aStringHash,
    2071             :                      Script aScriptCode, int32_t aAppUnitsPerDevUnit,
    2072             :                      mozilla::gfx::ShapedTextFlags aFlags,
    2073             :                      RoundingFlags aRounding)
    2074         108 :             : mLength(aLength),
    2075             :               mFlags(aFlags),
    2076             :               mScript(aScriptCode),
    2077             :               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
    2078             :               mHashKey(aStringHash
    2079         108 :                            + static_cast<int32_t>(aScriptCode)
    2080         108 :                            + aAppUnitsPerDevUnit * 0x100
    2081         216 :                            + uint16_t(aFlags) * 0x10000
    2082         108 :                            + int(aRounding)),
    2083             :               mTextIs8Bit(false),
    2084         216 :               mRounding(aRounding)
    2085             :         {
    2086             :             // We can NOT assert that TEXT_IS_8BIT is false in aFlags here,
    2087             :             // because this might be an 8bit-only word from a 16-bit textrun,
    2088             :             // in which case the text we're passed is still in 16-bit form,
    2089             :             // and we'll have to use an 8-to-16bit comparison in KeyEquals.
    2090         108 :             mText.mDouble = aText;
    2091         108 :         }
    2092             :     };
    2093             : 
    2094             :     class CacheHashEntry : public PLDHashEntryHdr {
    2095             :     public:
    2096             :         typedef const CacheHashKey &KeyType;
    2097             :         typedef const CacheHashKey *KeyTypePointer;
    2098             : 
    2099             :         // When constructing a new entry in the hashtable, the caller of Put()
    2100             :         // will fill us in.
    2101          32 :         explicit CacheHashEntry(KeyTypePointer aKey) { }
    2102             :         CacheHashEntry(const CacheHashEntry& toCopy) { NS_ERROR("Should not be called"); }
    2103           0 :         ~CacheHashEntry() { }
    2104             : 
    2105             :         bool KeyEquals(const KeyTypePointer aKey) const;
    2106             : 
    2107         127 :         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
    2108             : 
    2109         127 :         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
    2110         127 :             return aKey->mHashKey;
    2111             :         }
    2112             : 
    2113           0 :         size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2114             :         {
    2115           0 :             return aMallocSizeOf(mShapedWord.get());
    2116             :         }
    2117             : 
    2118             :         enum { ALLOW_MEMMOVE = true };
    2119             : 
    2120             :         mozilla::UniquePtr<gfxShapedWord> mShapedWord;
    2121             :     };
    2122             : 
    2123             :     mozilla::UniquePtr<nsTHashtable<CacheHashEntry> > mWordCache;
    2124             : 
    2125             :     static const uint32_t  kShapedWordCacheMaxAge = 3;
    2126             : 
    2127             :     bool                       mIsValid;
    2128             : 
    2129             :     // use synthetic bolding for environments where this is not supported
    2130             :     // by the platform
    2131             :     bool                       mApplySyntheticBold;
    2132             : 
    2133             :     bool                       mKerningSet;     // kerning explicitly set?
    2134             :     bool                       mKerningEnabled; // if set, on or off?
    2135             : 
    2136             :     bool                       mMathInitialized; // TryGetMathTable() called?
    2137             : 
    2138             :     nsExpirationState          mExpirationState;
    2139             :     gfxFontStyle               mStyle;
    2140             :     nsTArray<mozilla::UniquePtr<gfxGlyphExtents>> mGlyphExtentsArray;
    2141             :     mozilla::UniquePtr<nsTHashtable<nsPtrHashKey<GlyphChangeObserver>>>
    2142             :                                mGlyphChangeObservers;
    2143             : 
    2144             :     gfxFloat                   mAdjustedSize;
    2145             : 
    2146             :     // Conversion factor from font units to dev units; note that this may be
    2147             :     // zero (in the degenerate case where mAdjustedSize has become zero).
    2148             :     // This is OK because we only multiply by this factor, never divide.
    2149             :     float                      mFUnitsConvFactor;
    2150             : 
    2151             :     // the AA setting requested for this font - may affect glyph bounds
    2152             :     AntialiasOption            mAntialiasOption;
    2153             : 
    2154             :     // a copy of the font without antialiasing, if needed for separate
    2155             :     // measurement by mathml code
    2156             :     mozilla::UniquePtr<gfxFont>         mNonAAFont;
    2157             : 
    2158             :     // we create either or both of these shapers when needed, depending
    2159             :     // whether the font has graphite tables, and whether graphite shaping
    2160             :     // is actually enabled
    2161             :     mozilla::UniquePtr<gfxFontShaper>   mHarfBuzzShaper;
    2162             :     mozilla::UniquePtr<gfxFontShaper>   mGraphiteShaper;
    2163             : 
    2164             :     // if a userfont with unicode-range specified, contains map of *possible*
    2165             :     // ranges supported by font
    2166             :     RefPtr<gfxCharacterMap> mUnicodeRangeMap;
    2167             : 
    2168             :     RefPtr<mozilla::gfx::UnscaledFont> mUnscaledFont;
    2169             :     RefPtr<mozilla::gfx::ScaledFont> mAzureScaledFont;
    2170             : 
    2171             :     // For vertical metrics, created on demand.
    2172             :     mozilla::UniquePtr<const Metrics> mVerticalMetrics;
    2173             : 
    2174             :     // Table used for MathML layout.
    2175             :     mozilla::UniquePtr<gfxMathTable> mMathTable;
    2176             : 
    2177             :     // Helper for subclasses that want to initialize standard metrics from the
    2178             :     // tables of sfnt (TrueType/OpenType) fonts.
    2179             :     // This will use mFUnitsConvFactor if it is already set, else compute it
    2180             :     // from mAdjustedSize and the unitsPerEm in the font's 'head' table.
    2181             :     // Returns TRUE and sets mIsValid=TRUE if successful;
    2182             :     // Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
    2183             :     // Returns FALSE if the font does not appear to be an sfnt at all,
    2184             :     // and should be handled (if possible) using other APIs.
    2185             :     bool InitMetricsFromSfntTables(Metrics& aMetrics);
    2186             : 
    2187             :     // Helper to calculate various derived metrics from the results of
    2188             :     // InitMetricsFromSfntTables or equivalent platform code
    2189             :     void CalculateDerivedMetrics(Metrics& aMetrics);
    2190             : 
    2191             :     // some fonts have bad metrics, this method sanitize them.
    2192             :     // if this font has bad underline offset, aIsBadUnderlineFont should be true.
    2193             :     void SanitizeMetrics(Metrics *aMetrics, bool aIsBadUnderlineFont);
    2194             : 
    2195             :     bool RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint,
    2196             :                         uint32_t aGlyphId, SVGContextPaint* aContextPaint) const;
    2197             :     bool RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint,
    2198             :                         uint32_t aGlyphId, SVGContextPaint* aContextPaint,
    2199             :                         gfxTextRunDrawCallbacks *aCallbacks,
    2200             :                         bool& aEmittedGlyphs) const;
    2201             : 
    2202             :     bool RenderColorGlyph(DrawTarget* aDrawTarget,
    2203             :                           gfxContext* aContext,
    2204             :                           mozilla::gfx::ScaledFont* scaledFont,
    2205             :                           mozilla::gfx::GlyphRenderingOptions* renderingOptions,
    2206             :                           mozilla::gfx::DrawOptions drawOptions,
    2207             :                           const mozilla::gfx::Point& aPoint,
    2208             :                           uint32_t aGlyphId) const;
    2209             : 
    2210             :     // Bug 674909. When synthetic bolding text by drawing twice, need to
    2211             :     // render using a pixel offset in device pixels, otherwise text
    2212             :     // doesn't appear bolded, it appears as if a bad text shadow exists
    2213             :     // when a non-identity transform exists.  Use an offset factor so that
    2214             :     // the second draw occurs at a constant offset in device pixels.
    2215             :     // This helper calculates the scale factor we need to apply to the
    2216             :     // synthetic-bold offset.
    2217             :     static double CalcXScale(DrawTarget* aDrawTarget);
    2218             : };
    2219             : 
    2220             : // proportion of ascent used for x-height, if unable to read value from font
    2221             : #define DEFAULT_XHEIGHT_FACTOR 0.56f
    2222             : 
    2223             : // Parameters passed to gfxFont methods for drawing glyphs from a textrun.
    2224             : // The TextRunDrawParams are set up once per textrun; the FontDrawParams
    2225             : // are dependent on the specific font, so they are set per GlyphRun.
    2226             : 
    2227          42 : struct TextRunDrawParams {
    2228             :     RefPtr<mozilla::gfx::DrawTarget> dt;
    2229             :     gfxContext              *context;
    2230             :     gfxFont::Spacing        *spacing;
    2231             :     gfxTextRunDrawCallbacks *callbacks;
    2232             :     mozilla::SVGContextPaint *runContextPaint;
    2233             :     mozilla::gfx::Color      fontSmoothingBGColor;
    2234             :     gfxFloat                 direction;
    2235             :     double                   devPerApp;
    2236             :     nscolor                  textStrokeColor;
    2237             :     gfxPattern              *textStrokePattern;
    2238             :     const mozilla::gfx::StrokeOptions *strokeOpts;
    2239             :     const mozilla::gfx::DrawOptions   *drawOpts;
    2240             :     DrawMode                 drawMode;
    2241             :     bool                     isVerticalRun;
    2242             :     bool                     isRTL;
    2243             :     bool                     paintSVGGlyphs;
    2244             : };
    2245             : 
    2246          42 : struct FontDrawParams {
    2247             :     RefPtr<mozilla::gfx::ScaledFont>            scaledFont;
    2248             :     RefPtr<mozilla::gfx::GlyphRenderingOptions> renderingOptions;
    2249             :     mozilla::SVGContextPaint *contextPaint;
    2250             :     mozilla::gfx::Matrix     *passedInvMatrix;
    2251             :     mozilla::gfx::Matrix      matInv;
    2252             :     double                    synBoldOnePixelOffset;
    2253             :     int32_t                   extraStrikes;
    2254             :     mozilla::gfx::DrawOptions drawOptions;
    2255             :     bool                      isVerticalFont;
    2256             :     bool                      haveSVGGlyphs;
    2257             :     bool                      haveColorGlyphs;
    2258             : };
    2259             : 
    2260             : struct EmphasisMarkDrawParams {
    2261             :     gfxContext* context;
    2262             :     gfxFont::Spacing* spacing;
    2263             :     gfxTextRun* mark;
    2264             :     gfxFloat advance;
    2265             :     gfxFloat direction;
    2266             :     bool isVertical;
    2267             : };
    2268             : 
    2269             : #endif

Generated by: LCOV version 1.13