1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=4 et sw=2 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/. */
15 #include "gfxFontConstants.h"
16 #include "gfxSkipChars.h"
17 #include "gfxPlatform.h"
18 #include "gfxPlatformFontList.h"
19 #include "gfxUserFontSet.h"
20 #include "mozilla/MemoryReporting.h"
21 #include "mozilla/RefPtr.h"
25 #include "nsTHashSet.h"
26 #include "nsTextFrameUtils.h"
28 #include "harfbuzz/hb.h"
29 #include "nsUnicodeScriptCodes.h"
31 #include "nsFrameList.h"
32 #include "X11UndefineNone.h"
34 #ifdef DEBUG_FRAME_DUMP
41 class nsLanguageAtomService
;
42 class gfxMissingFontRecorder
;
45 class PostTraversalTask
;
46 class SVGContextPaint
;
47 enum class StyleHyphens
: uint8_t;
48 }; // namespace mozilla
51 * Callback for Draw() to use when drawing text with mode
52 * DrawMode::GLYPH_PATH.
54 struct gfxTextRunDrawCallbacks
{
56 * Constructs a new DrawCallbacks object.
58 * @param aShouldPaintSVGGlyphs If true, SVG glyphs will be painted. If
59 * false, SVG glyphs will not be painted; fallback plain glyphs are not
62 explicit gfxTextRunDrawCallbacks(bool aShouldPaintSVGGlyphs
= false)
63 : mShouldPaintSVGGlyphs(aShouldPaintSVGGlyphs
) {}
66 * Called when a path has been emitted to the gfxContext when
67 * painting a text run. This can be called any number of times,
68 * due to partial ligatures and intervening SVG glyphs.
70 virtual void NotifyGlyphPathEmitted() = 0;
72 bool mShouldPaintSVGGlyphs
;
76 * gfxTextRun is an abstraction for drawing and measuring substrings of a run
77 * of text. It stores runs of positioned glyph data, each run having a single
78 * gfxFont. The glyphs are associated with a string of source text, and the
79 * gfxTextRun APIs take parameters that are offsets into that source text.
81 * gfxTextRuns are mostly immutable. The only things that can change are
82 * inter-cluster spacing and line break placement. Spacing is always obtained
83 * lazily by methods that need it, it is not cached. Line breaks are stored
84 * persistently (insofar as they affect the shaping of glyphs; gfxTextRun does
85 * not actually do anything to explicitly account for line breaks). Initially
86 * there are no line breaks. The textrun can record line breaks before or after
87 * any given cluster. (Line breaks specified inside clusters are ignored.)
89 * It is important that zero-length substrings are handled correctly. This will
92 class gfxTextRun
: public gfxShapedText
{
93 NS_INLINE_DECL_REFCOUNTING(gfxTextRun
);
96 // Override operator delete to properly free the object that was
97 // allocated via malloc.
98 void operator delete(void* p
) { free(p
); }
100 virtual ~gfxTextRun();
103 typedef gfxFont::RunMetrics Metrics
;
104 typedef mozilla::gfx::DrawTarget DrawTarget
;
106 // Public textrun API for general use
108 bool IsClusterStart(uint32_t aPos
) const {
109 MOZ_ASSERT(aPos
< GetLength());
110 return mCharacterGlyphs
[aPos
].IsClusterStart();
112 bool IsLigatureGroupStart(uint32_t aPos
) const {
113 MOZ_ASSERT(aPos
< GetLength());
114 return mCharacterGlyphs
[aPos
].IsLigatureGroupStart();
116 bool CanBreakLineBefore(uint32_t aPos
) const {
117 return CanBreakBefore(aPos
) == CompressedGlyph::FLAG_BREAK_TYPE_NORMAL
;
119 bool CanHyphenateBefore(uint32_t aPos
) const {
120 return CanBreakBefore(aPos
) == CompressedGlyph::FLAG_BREAK_TYPE_HYPHEN
;
123 // Returns a gfxShapedText::CompressedGlyph::FLAG_BREAK_TYPE_* value
124 // as defined in gfxFont.h (may be NONE, NORMAL or HYPHEN).
125 uint8_t CanBreakBefore(uint32_t aPos
) const {
126 MOZ_ASSERT(aPos
< GetLength());
127 return mCharacterGlyphs
[aPos
].CanBreakBefore();
130 bool CharIsSpace(uint32_t aPos
) const {
131 MOZ_ASSERT(aPos
< GetLength());
132 return mCharacterGlyphs
[aPos
].CharIsSpace();
134 bool CharIsTab(uint32_t aPos
) const {
135 MOZ_ASSERT(aPos
< GetLength());
136 return mCharacterGlyphs
[aPos
].CharIsTab();
138 bool CharIsNewline(uint32_t aPos
) const {
139 MOZ_ASSERT(aPos
< GetLength());
140 return mCharacterGlyphs
[aPos
].CharIsNewline();
142 bool CharMayHaveEmphasisMark(uint32_t aPos
) const {
143 MOZ_ASSERT(aPos
< GetLength());
144 return mCharacterGlyphs
[aPos
].CharMayHaveEmphasisMark();
146 bool CharIsFormattingControl(uint32_t aPos
) const {
147 MOZ_ASSERT(aPos
< GetLength());
148 return mCharacterGlyphs
[aPos
].CharIsFormattingControl();
151 // All offsets are in terms of the string passed into MakeTextRun.
153 // Describe range [start, end) of a text run. The range is
154 // restricted to grapheme cluster boundaries.
158 uint32_t Length() const { return end
- start
; }
160 Range() : start(0), end(0) {}
161 Range(uint32_t aStart
, uint32_t aEnd
) : start(aStart
), end(aEnd
) {}
162 explicit Range(const gfxTextRun
* aTextRun
)
163 : start(0), end(aTextRun
->GetLength()) {}
166 // All coordinates are in layout/app units
169 * Set the potential linebreaks for a substring of the textrun. These are
170 * the "allow break before" points. Initially, there are no potential
173 * This can change glyphs and/or geometry! Some textruns' shapes
174 * depend on potential line breaks (e.g., title-case-converting textruns).
175 * This function is virtual so that those textruns can reshape themselves.
177 * @return true if this changed the linebreaks, false if the new line
178 * breaks are the same as the old
180 virtual bool SetPotentialLineBreaks(Range aRange
,
181 const uint8_t* aBreakBefore
);
183 enum class HyphenType
: uint8_t {
184 // Code in BreakAndMeasureText depends on the ordering of these values!
188 AutoWithManualInSameWord
,
189 AutoWithoutManualInSameWord
192 static bool IsOptionalHyphenBreak(HyphenType aType
) {
193 return aType
>= HyphenType::Soft
;
196 struct HyphenationState
{
197 uint32_t mostRecentBoundary
= 0;
198 bool hasManualHyphen
= false;
199 bool hasExplicitHyphen
= false;
200 bool hasAutoHyphen
= false;
204 * Layout provides PropertyProvider objects. These allow detection of
205 * potential line break points and computation of spacing. We pass the data
206 * this way to allow lazy data acquisition; for example BreakAndMeasureText
207 * will want to only ask for properties of text it's actually looking at.
209 * NOTE that requested spacing may not actually be applied, if the textrun
210 * is unable to apply it in some context. Exception: spacing around a
211 * whitespace character MUST always be applied.
213 class PropertyProvider
{
215 // Detect hyphenation break opportunities in the given range; breaks
216 // not at cluster boundaries will be ignored.
217 virtual void GetHyphenationBreaks(Range aRange
,
218 HyphenType
* aBreakBefore
) const = 0;
220 // Returns the provider's hyphenation setting, so callers can decide
221 // whether it is necessary to call GetHyphenationBreaks.
222 // Result is an StyleHyphens value.
223 virtual mozilla::StyleHyphens
GetHyphensOption() const = 0;
225 // Returns the extra width that will be consumed by a hyphen. This should
226 // be constant for a given textrun.
227 virtual gfxFloat
GetHyphenWidth() const = 0;
229 typedef gfxFont::Spacing Spacing
;
232 * Get the spacing around the indicated characters. Spacing must be zero
233 * inside clusters. In other words, if character i is not
234 * CLUSTER_START, then character i-1 must have zero after-spacing and
235 * character i must have zero before-spacing.
237 virtual void GetSpacing(Range aRange
, Spacing
* aSpacing
) const = 0;
239 // Returns a gfxContext that can be used to measure the hyphen glyph.
240 // Only called if the hyphen width is requested.
241 virtual already_AddRefed
<DrawTarget
> GetDrawTarget() const = 0;
243 // Return the appUnitsPerDevUnit value to be used when measuring.
244 // Only called if the hyphen width is requested.
245 virtual uint32_t GetAppUnitsPerDevUnit() const = 0;
248 struct MOZ_STACK_CLASS DrawParams
{
250 DrawMode drawMode
= DrawMode::GLYPH_FILL
;
251 nscolor textStrokeColor
= 0;
252 gfxPattern
* textStrokePattern
= nullptr;
253 const mozilla::gfx::StrokeOptions
* strokeOpts
= nullptr;
254 const mozilla::gfx::DrawOptions
* drawOpts
= nullptr;
255 PropertyProvider
* provider
= nullptr;
256 // If non-null, the advance width of the substring is set.
257 gfxFloat
* advanceWidth
= nullptr;
258 mozilla::SVGContextPaint
* contextPaint
= nullptr;
259 gfxTextRunDrawCallbacks
* callbacks
= nullptr;
260 bool allowGDI
= true;
261 explicit DrawParams(gfxContext
* aContext
) : context(aContext
) {}
265 * Draws a substring. Uses only GetSpacing from aBreakProvider.
266 * The provided point is the baseline origin on the left of the string
267 * for LTR, on the right of the string for RTL.
269 * Drawing should respect advance widths in the sense that for LTR runs,
270 * Draw(Range(start, middle), pt, ...) followed by
271 * Draw(Range(middle, end), gfxPoint(pt.x + advance, pt.y), ...)
272 * should have the same effect as
273 * Draw(Range(start, end), pt, ...)
275 * For RTL runs the rule is:
276 * Draw(Range(middle, end), pt, ...) followed by
277 * Draw(Range(start, middle), gfxPoint(pt.x + advance, pt.y), ...)
278 * should have the same effect as
279 * Draw(Range(start, end), pt, ...)
281 * Glyphs should be drawn in logical content order, which can be significant
282 * if they overlap (perhaps due to negative spacing).
284 void Draw(const Range aRange
, const mozilla::gfx::Point aPt
,
285 const DrawParams
& aParams
) const;
288 * Draws the emphasis marks for this text run. Uses only GetSpacing
289 * from aProvider. The provided point is the baseline origin of the
290 * line of emphasis marks.
292 void DrawEmphasisMarks(gfxContext
* aContext
, gfxTextRun
* aMark
,
293 gfxFloat aMarkAdvance
, mozilla::gfx::Point aPt
,
294 Range aRange
, PropertyProvider
* aProvider
) const;
297 * Computes the ReflowMetrics for a substring.
298 * Uses GetSpacing from aBreakProvider.
299 * @param aBoundingBoxType which kind of bounding box (loose/tight)
301 Metrics
MeasureText(Range aRange
, gfxFont::BoundingBoxType aBoundingBoxType
,
302 DrawTarget
* aDrawTargetForTightBoundingBox
,
303 PropertyProvider
* aProvider
) const;
305 Metrics
MeasureText(gfxFont::BoundingBoxType aBoundingBoxType
,
306 DrawTarget
* aDrawTargetForTightBoundingBox
,
307 PropertyProvider
* aProvider
= nullptr) const {
308 return MeasureText(Range(this), aBoundingBoxType
,
309 aDrawTargetForTightBoundingBox
, aProvider
);
313 * Computes just the advance width for a substring.
314 * Uses GetSpacing from aBreakProvider.
315 * If aSpacing is not null, the spacing attached before and after
316 * the substring would be returned in it. NOTE: the spacing is
317 * included in the advance width.
319 gfxFloat
GetAdvanceWidth(Range aRange
, PropertyProvider
* aProvider
,
320 PropertyProvider::Spacing
* aSpacing
= nullptr) const;
322 gfxFloat
GetAdvanceWidth() const {
323 return GetAdvanceWidth(Range(this), nullptr);
327 * Computes the minimum advance width for a substring assuming line
328 * breaking is allowed everywhere.
330 gfxFloat
GetMinAdvanceWidth(Range aRange
);
333 * Clear all stored line breaks for the given range (both before and after),
334 * and then set the line-break state before aRange.start to aBreakBefore and
335 * after the last cluster to aBreakAfter.
337 * We require that before and after line breaks be consistent. For clusters
338 * i and i+1, we require that if there is a break after cluster i, a break
339 * will be specified before cluster i+1. This may be temporarily violated
340 * (e.g. after reflowing line L and before reflowing line L+1); to handle
341 * these temporary violations, we say that there is a break betwen i and i+1
342 * if a break is specified after i OR a break is specified before i+1.
344 * This can change textrun geometry! The existence of a linebreak can affect
345 * the advance width of the cluster before the break (when kerning) or the
346 * geometry of one cluster before the break or any number of clusters
347 * after the break. (The one-cluster-before-the-break limit is somewhat
348 * arbitrary; if some scripts require breaking it, then we need to
349 * alter nsTextFrame::TrimTrailingWhitespace, perhaps drastically becase
350 * it could affect the layout of frames before it...)
352 * We return true if glyphs or geometry changed, false otherwise. This
353 * function is virtual so that gfxTextRun subclasses can reshape
356 * @param aAdvanceWidthDelta if non-null, returns the change in advance
357 * width of the given range.
359 virtual bool SetLineBreaks(Range aRange
, bool aLineBreakBefore
,
360 bool aLineBreakAfter
,
361 gfxFloat
* aAdvanceWidthDelta
);
365 // Measure the range of text as if there is no break before it.
366 eSuppressInitialBreak
,
367 // Measure the range of text as if it contains no break
371 void ClassifyAutoHyphenations(uint32_t aStart
, Range aRange
,
372 nsTArray
<HyphenType
>& aHyphenBuffer
,
373 HyphenationState
* aWordState
);
376 * Finds the longest substring that will fit into the given width.
377 * Uses GetHyphenationBreaks and GetSpacing from aProvider.
378 * Guarantees the following:
379 * -- 0 <= result <= aMaxLength
380 * -- result is the maximal value of N such that either
381 * N < aMaxLength && line break at N &&
382 * GetAdvanceWidth(Range(aStart, N), aProvider) <= aWidth
383 * OR N < aMaxLength && hyphen break at N &&
384 * GetAdvanceWidth(Range(aStart, N), aProvider) +
385 * GetHyphenWidth() <= aWidth
386 * OR N == aMaxLength &&
387 * GetAdvanceWidth(Range(aStart, N), aProvider) <= aWidth
388 * where GetAdvanceWidth assumes the effect of
389 * SetLineBreaks(Range(aStart, N),
390 * aLineBreakBefore, N < aMaxLength, aProvider)
391 * -- if no such N exists, then result is the smallest N such that
392 * N < aMaxLength && line break at N
393 * OR N < aMaxLength && hyphen break at N
396 * The call has the effect of
397 * SetLineBreaks(Range(aStart, result), aLineBreakBefore,
398 * result < aMaxLength, aProvider)
399 * and the returned metrics and the invariants above reflect this.
401 * @param aMaxLength this can be UINT32_MAX, in which case the length used
402 * is up to the end of the string
403 * @param aLineBreakBefore set to true if and only if there is an actual
404 * line break at the start of this string.
405 * @param aSuppressBreak what break should be suppressed.
406 * @param aTrimWhitespace if non-null, then we allow a trailing run of
407 * spaces to be trimmed; the width of the space(s) will not be included in
408 * the measured string width for comparison with the limit aWidth, and
409 * trimmed spaces will not be included in returned metrics. The width
410 * of the trimmed spaces will be returned in aTrimWhitespace.
411 * Trimmed spaces are still counted in the "characters fit" result.
412 * @param aHangWhitespace true if we allow whitespace to overflow the
413 * container at a soft-wrap
414 * @param aMetrics if non-null, we fill this in for the returned substring.
415 * If a hyphenation break was used, the hyphen is NOT included in the returned
417 * @param aBoundingBoxType whether to make the bounding box in aMetrics tight
418 * @param aDrawTargetForTightBoundingbox a reference DrawTarget to get the
419 * tight bounding box, if requested
420 * @param aUsedHyphenation if non-null, records if we selected a hyphenation
422 * @param aLastBreak if non-null and result is aMaxLength, we set this to
423 * the maximal N such that
424 * N < aMaxLength && line break at N &&
425 * GetAdvanceWidth(Range(aStart, N), aProvider) <= aWidth
426 * OR N < aMaxLength && hyphen break at N &&
427 * GetAdvanceWidth(Range(aStart, N), aProvider) +
428 * GetHyphenWidth() <= aWidth
429 * or UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
431 * SetLineBreaks(Range(aStart, N), aLineBreakBefore,
432 * N < aMaxLength, aProvider)
434 * @param aCanWordWrap true if we can break between any two grapheme
435 * clusters. This is set by overflow-wrap|word-wrap: break-word
437 * @param aBreakPriority in/out the priority of the break opportunity
438 * saved in the line. If we are prioritizing break opportunities, we will
439 * not set a break with a lower priority. @see gfxBreakPriority.
441 * Note that negative advance widths are possible especially if negative
442 * spacing is provided.
444 uint32_t BreakAndMeasureText(uint32_t aStart
, uint32_t aMaxLength
,
445 bool aLineBreakBefore
, gfxFloat aWidth
,
446 PropertyProvider
* aProvider
,
447 SuppressBreak aSuppressBreak
,
448 gfxFloat
* aTrimWhitespace
, bool aHangWhitespace
,
450 gfxFont::BoundingBoxType aBoundingBoxType
,
451 DrawTarget
* aDrawTargetForTightBoundingBox
,
452 bool* aUsedHyphenation
, uint32_t* aLastBreak
,
453 bool aCanWordWrap
, bool aCanWhitespaceWrap
,
454 gfxBreakPriority
* aBreakPriority
);
458 void* GetUserData() const { return mUserData
; }
459 void SetUserData(void* aUserData
) { mUserData
= aUserData
; }
461 void SetFlagBits(nsTextFrameUtils::Flags aFlags
) { mFlags2
|= aFlags
; }
462 void ClearFlagBits(nsTextFrameUtils::Flags aFlags
) { mFlags2
&= ~aFlags
; }
463 const gfxSkipChars
& GetSkipChars() const { return mSkipChars
; }
464 gfxFontGroup
* GetFontGroup() const { return mFontGroup
; }
466 // Call this, don't call "new gfxTextRun" directly. This does custom
467 // allocation and initialization
468 static already_AddRefed
<gfxTextRun
> Create(
469 const gfxTextRunFactory::Parameters
* aParams
, uint32_t aLength
,
470 gfxFontGroup
* aFontGroup
, mozilla::gfx::ShapedTextFlags aFlags
,
471 nsTextFrameUtils::Flags aFlags2
);
473 // The text is divided into GlyphRuns as necessary. (In the vast majority
474 // of cases, a gfxTextRun contains just a single GlyphRun.)
476 RefPtr
<gfxFont
> mFont
; // never null in a valid GlyphRun
477 uint32_t mCharacterOffset
; // into original UTF16 string
478 mozilla::gfx::ShapedTextFlags
479 mOrientation
; // gfxTextRunFactory::TEXT_ORIENT_* value
480 FontMatchType mMatchType
;
481 bool mIsCJK
; // Whether the text was a CJK script run (used to decide if
482 // text-decoration-skip-ink should not be applied)
484 // Set up the properties (but NOT offset) of the GlyphRun.
485 void SetProperties(gfxFont
* aFont
,
486 mozilla::gfx::ShapedTextFlags aOrientation
, bool aIsCJK
,
487 FontMatchType aMatchType
) {
489 mOrientation
= aOrientation
;
491 mMatchType
= aMatchType
;
494 // Return whether the GlyphRun matches the given properties;
495 // the given FontMatchType will be added to the run if not present.
496 bool Matches(gfxFont
* aFont
, mozilla::gfx::ShapedTextFlags aOrientation
,
497 bool aIsCJK
, FontMatchType aMatchType
) {
498 if (mFont
== aFont
&& mOrientation
== aOrientation
&& mIsCJK
== aIsCJK
) {
499 mMatchType
.kind
|= aMatchType
.kind
;
500 if (mMatchType
.generic
== mozilla::StyleGenericFontFamily::None
) {
501 mMatchType
.generic
= aMatchType
.generic
;
509 // Script run codes that we will mark as CJK to suppress skip-ink behavior.
510 static inline bool IsCJKScript(Script aScript
) {
512 case Script::BOPOMOFO
:
515 case Script::HIRAGANA
:
516 case Script::KATAKANA
:
517 case Script::KATAKANA_OR_HIRAGANA
:
518 case Script::SIMPLIFIED_HAN
:
519 case Script::TRADITIONAL_HAN
:
520 case Script::JAPANESE
:
522 case Script::HAN_WITH_BOPOMOFO
:
530 class MOZ_STACK_CLASS GlyphRunIterator
{
532 GlyphRunIterator(const gfxTextRun
* aTextRun
, Range aRange
,
533 bool aReverse
= false)
534 : mTextRun(aTextRun
),
535 mDirection(aReverse
? -1 : 1),
536 mStartOffset(aRange
.start
),
537 mEndOffset(aRange
.end
) {
538 mNextIndex
= mTextRun
->FindFirstGlyphRunContaining(
539 aReverse
? aRange
.end
- 1 : aRange
.start
);
542 const GlyphRun
* GetGlyphRun() const { return mGlyphRun
; }
543 uint32_t GetStringStart() const { return mStringStart
; }
544 uint32_t GetStringEnd() const { return mStringEnd
; }
547 const gfxTextRun
* mTextRun
;
548 MOZ_INIT_OUTSIDE_CTOR
const GlyphRun
* mGlyphRun
;
549 MOZ_INIT_OUTSIDE_CTOR
uint32_t mStringStart
;
550 MOZ_INIT_OUTSIDE_CTOR
uint32_t mStringEnd
;
551 const int32_t mDirection
;
553 uint32_t mStartOffset
;
557 class GlyphRunOffsetComparator
{
559 bool Equals(const GlyphRun
& a
, const GlyphRun
& b
) const {
560 return a
.mCharacterOffset
== b
.mCharacterOffset
;
563 bool LessThan(const GlyphRun
& a
, const GlyphRun
& b
) const {
564 return a
.mCharacterOffset
< b
.mCharacterOffset
;
568 friend class GlyphRunIterator
;
569 friend class FontSelector
;
571 // API for setting up the textrun glyphs. Should only be called by
572 // things that construct textruns.
574 * We've found a run of text that should use a particular font. Call this
575 * only during initialization when font substitution has been computed.
576 * Call it before setting up the glyphs for the characters in this run;
577 * SetMissingGlyph requires that the correct glyphrun be installed.
579 * If aForceNewRun, a new glyph run will be added, even if the
580 * previously added run uses the same font. If glyph runs are
581 * added out of strictly increasing aStartCharIndex order (via
582 * force), then SortGlyphRuns must be called after all glyph runs
583 * are added before any further operations are performed with this
586 void AddGlyphRun(gfxFont
* aFont
, FontMatchType aMatchType
,
587 uint32_t aUTF16Offset
, bool aForceNewRun
,
588 mozilla::gfx::ShapedTextFlags aOrientation
, bool aIsCJK
);
589 void ResetGlyphRuns() {
590 if (mHasGlyphRunArray
) {
591 MOZ_ASSERT(mGlyphRunArray
.Length() > 1);
592 // Discard all but the first GlyphRun...
593 mGlyphRunArray
.TruncateLength(1);
594 // ...and then convert to the single-run representation.
595 ConvertFromGlyphRunArray();
597 // Clear out the one remaining GlyphRun.
598 mSingleGlyphRun
.mFont
= nullptr;
600 void SortGlyphRuns();
601 void SanitizeGlyphRuns();
603 const CompressedGlyph
* GetCharacterGlyphs() const final
{
604 MOZ_ASSERT(mCharacterGlyphs
, "failed to initialize mCharacterGlyphs");
605 return mCharacterGlyphs
;
607 CompressedGlyph
* GetCharacterGlyphs() final
{
608 MOZ_ASSERT(mCharacterGlyphs
, "failed to initialize mCharacterGlyphs");
609 return mCharacterGlyphs
;
612 // clean out results from shaping in progress, used for fallback scenarios
613 void ClearGlyphsAndCharacters();
615 void SetSpaceGlyph(gfxFont
* aFont
, DrawTarget
* aDrawTarget
,
617 mozilla::gfx::ShapedTextFlags aOrientation
);
619 // Set the glyph data for the given character index to the font's
620 // space glyph, IF this can be done as a "simple" glyph record
621 // (not requiring a DetailedGlyph entry). This avoids the need to call
622 // the font shaper and go through the shaped-word cache for most spaces.
624 // The parameter aSpaceChar is the original character code for which
625 // this space glyph is being used; if this is U+0020, we need to record
626 // that it could be trimmed at a run edge, whereas other kinds of space
627 // (currently just U+00A0) would not be trimmable/breakable.
629 // Returns true if it was able to set simple glyph data for the space;
630 // if it returns false, the caller needs to fall back to some other
631 // means to create the necessary (detailed) glyph data.
632 bool SetSpaceGlyphIfSimple(gfxFont
* aFont
, uint32_t aCharIndex
,
634 mozilla::gfx::ShapedTextFlags aOrientation
);
636 // Record the positions of specific characters that layout may need to
637 // detect in the textrun, even though it doesn't have an explicit copy
638 // of the original text. These are recorded using flag bits in the
639 // CompressedGlyph record; if necessary, we convert "simple" glyph records
640 // to "complex" ones as the Tab and Newline flags are not present in
641 // simple CompressedGlyph records.
642 void SetIsTab(uint32_t aIndex
) { EnsureComplexGlyph(aIndex
).SetIsTab(); }
643 void SetIsNewline(uint32_t aIndex
) {
644 EnsureComplexGlyph(aIndex
).SetIsNewline();
646 void SetNoEmphasisMark(uint32_t aIndex
) {
647 EnsureComplexGlyph(aIndex
).SetNoEmphasisMark();
649 void SetIsFormattingControl(uint32_t aIndex
) {
650 EnsureComplexGlyph(aIndex
).SetIsFormattingControl();
654 * Prefetch all the glyph extents needed to ensure that Measure calls
655 * on this textrun not requesting tight boundingBoxes will succeed. Note
656 * that some glyph extents might not be fetched due to OOM or other
659 void FetchGlyphExtents(DrawTarget
* aRefDrawTarget
);
661 const GlyphRun
* GetGlyphRuns(uint32_t* aNumGlyphRuns
) const {
662 if (mHasGlyphRunArray
) {
663 *aNumGlyphRuns
= mGlyphRunArray
.Length();
664 return mGlyphRunArray
.Elements();
666 *aNumGlyphRuns
= mSingleGlyphRun
.mFont
? 1 : 0;
667 return &mSingleGlyphRun
;
671 const GlyphRun
* TrailingGlyphRun() const {
673 const GlyphRun
* runs
= GetGlyphRuns(&count
);
674 return count
? runs
+ count
- 1 : nullptr;
677 // Returns the index of the GlyphRun containing the given offset.
678 // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
679 uint32_t FindFirstGlyphRunContaining(uint32_t aOffset
) const;
681 // Copy glyph data from a ShapedWord into this textrun.
682 void CopyGlyphDataFrom(gfxShapedWord
* aSource
, uint32_t aStart
);
684 // Copy glyph data for a range of characters from aSource to this
686 void CopyGlyphDataFrom(gfxTextRun
* aSource
, Range aRange
, uint32_t aDest
);
688 // Tell the textrun to release its reference to its creating gfxFontGroup
689 // immediately, rather than on destruction. This is used for textruns
690 // that are actually owned by a gfxFontGroup, so that they don't keep it
691 // permanently alive due to a circular reference. (The caller of this is
692 // taking responsibility for ensuring the textrun will not outlive its
694 void ReleaseFontGroup();
696 struct LigatureData
{
697 // textrun range of the containing ligature
699 // appunits advance to the start of the ligature part within the ligature;
700 // never includes any spacing
701 gfxFloat mPartAdvance
;
702 // appunits width of the ligature part; includes before-spacing
703 // when the part is at the start of the ligature, and after-spacing
704 // when the part is as the end of the ligature
707 bool mClipBeforePart
;
711 // return storage used by this run, for memory reporter;
712 // nsTransformedTextRun needs to override this as it holds additional data
713 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
)
715 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
)
718 nsTextFrameUtils::Flags
GetFlags2() const { return mFlags2
; }
720 // Get the size, if it hasn't already been gotten, marking as it goes.
721 size_t MaybeSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) {
722 if (mFlags2
& nsTextFrameUtils::Flags::RunSizeAccounted
) {
725 mFlags2
|= nsTextFrameUtils::Flags::RunSizeAccounted
;
726 return SizeOfIncludingThis(aMallocSizeOf
);
728 void ResetSizeOfAccountingFlags() {
729 mFlags2
&= ~nsTextFrameUtils::Flags::RunSizeAccounted
;
732 // shaping state - for some font features, fallback is required that
733 // affects the entire run. for example, fallback for one script/font
734 // portion of a textrun requires fallback to be applied to the entire run
736 enum ShapingState
: uint8_t {
737 eShapingState_Normal
, // default state
738 eShapingState_ShapingWithFeature
, // have shaped with feature
739 eShapingState_ShapingWithFallback
, // have shaped with fallback
740 eShapingState_Aborted
, // abort initial iteration
741 eShapingState_ForceFallbackFeature
// redo with fallback forced on
744 ShapingState
GetShapingState() const { return mShapingState
; }
745 void SetShapingState(ShapingState aShapingState
) {
746 mShapingState
= aShapingState
;
749 int32_t GetAdvanceForGlyph(uint32_t aIndex
) const {
750 const CompressedGlyph
& glyphData
= mCharacterGlyphs
[aIndex
];
751 if (glyphData
.IsSimpleGlyph()) {
752 return glyphData
.GetSimpleAdvance();
754 uint32_t glyphCount
= glyphData
.GetGlyphCount();
758 const DetailedGlyph
* details
= GetDetailedGlyphs(aIndex
);
760 for (uint32_t j
= 0; j
< glyphCount
; ++j
, ++details
) {
761 advance
+= details
->mAdvance
;
766 #ifdef DEBUG_FRAME_DUMP
767 void Dump(FILE* aOutput
= stderr
);
772 * Create a textrun, and set its mCharacterGlyphs to point immediately
773 * after the base object; this is ONLY used in conjunction with placement
774 * new, after allocating a block large enough for the glyph records to
775 * follow the base textrun object.
777 gfxTextRun(const gfxTextRunFactory::Parameters
* aParams
, uint32_t aLength
,
778 gfxFontGroup
* aFontGroup
, mozilla::gfx::ShapedTextFlags aFlags
,
779 nsTextFrameUtils::Flags aFlags2
);
782 * Helper for the Create() factory method to allocate the required
783 * glyph storage for a textrun object with the basic size aSize,
784 * plus room for aLength glyph records.
786 static void* AllocateStorageForTextRun(size_t aSize
, uint32_t aLength
);
788 // Pointer to the array of CompressedGlyph records; must be initialized
789 // when the object is constructed.
790 CompressedGlyph
* mCharacterGlyphs
;
793 // **** general helpers ****
795 // Get the total advance for a range of glyphs.
796 int32_t GetAdvanceForGlyphs(Range aRange
) const;
798 // Spacing for characters outside the range aSpacingStart/aSpacingEnd
799 // is assumed to be zero; such characters are not passed to aProvider.
800 // This is useful to protect aProvider from being passed character indices
801 // it is not currently able to handle.
802 bool GetAdjustedSpacingArray(
803 Range aRange
, PropertyProvider
* aProvider
, Range aSpacingRange
,
804 nsTArray
<PropertyProvider::Spacing
>* aSpacing
) const;
806 CompressedGlyph
& EnsureComplexGlyph(uint32_t aIndex
) {
807 gfxShapedText::EnsureComplexGlyph(aIndex
, mCharacterGlyphs
[aIndex
]);
808 return mCharacterGlyphs
[aIndex
];
811 // **** ligature helpers ****
812 // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
813 // to handle requests that begin or end inside a ligature)
815 // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
816 LigatureData
ComputeLigatureData(Range aPartRange
,
817 PropertyProvider
* aProvider
) const;
818 gfxFloat
ComputePartialLigatureWidth(Range aPartRange
,
819 PropertyProvider
* aProvider
) const;
820 void DrawPartialLigature(gfxFont
* aFont
, Range aRange
,
821 mozilla::gfx::Point
* aPt
,
822 PropertyProvider
* aProvider
,
823 TextRunDrawParams
& aParams
,
824 mozilla::gfx::ShapedTextFlags aOrientation
) const;
825 // Advance aRange.start to the start of the nearest ligature, back
826 // up aRange.end to the nearest ligature end; may result in
827 // aRange->start == aRange->end.
828 void ShrinkToLigatureBoundaries(Range
* aRange
) const;
829 // result in appunits
830 gfxFloat
GetPartialLigatureWidth(Range aRange
,
831 PropertyProvider
* aProvider
) const;
832 void AccumulatePartialLigatureMetrics(
833 gfxFont
* aFont
, Range aRange
, gfxFont::BoundingBoxType aBoundingBoxType
,
834 DrawTarget
* aRefDrawTarget
, PropertyProvider
* aProvider
,
835 mozilla::gfx::ShapedTextFlags aOrientation
, Metrics
* aMetrics
) const;
837 // **** measurement helper ****
838 void AccumulateMetricsForRun(gfxFont
* aFont
, Range aRange
,
839 gfxFont::BoundingBoxType aBoundingBoxType
,
840 DrawTarget
* aRefDrawTarget
,
841 PropertyProvider
* aProvider
, Range aSpacingRange
,
842 mozilla::gfx::ShapedTextFlags aOrientation
,
843 Metrics
* aMetrics
) const;
845 // **** drawing helper ****
846 void DrawGlyphs(gfxFont
* aFont
, Range aRange
, mozilla::gfx::Point
* aPt
,
847 PropertyProvider
* aProvider
, Range aSpacingRange
,
848 TextRunDrawParams
& aParams
,
849 mozilla::gfx::ShapedTextFlags aOrientation
) const;
851 // The textrun holds either a single GlyphRun -or- an array;
852 // the flag mHasGlyphRunArray tells us which is present.
854 GlyphRun mSingleGlyphRun
;
855 nsTArray
<GlyphRun
> mGlyphRunArray
;
858 void ConvertToGlyphRunArray() {
859 MOZ_ASSERT(!mHasGlyphRunArray
&& mSingleGlyphRun
.mFont
);
860 GlyphRun tmp
= std::move(mSingleGlyphRun
);
861 mSingleGlyphRun
.~GlyphRun();
862 new (&mGlyphRunArray
) nsTArray
<GlyphRun
>(2);
863 mGlyphRunArray
.AppendElement(std::move(tmp
));
864 mHasGlyphRunArray
= true;
867 void ConvertFromGlyphRunArray() {
868 MOZ_ASSERT(mHasGlyphRunArray
&& mGlyphRunArray
.Length() == 1);
869 GlyphRun tmp
= std::move(mGlyphRunArray
[0]);
870 mGlyphRunArray
.~nsTArray
<GlyphRun
>();
871 new (&mSingleGlyphRun
) GlyphRun(std::move(tmp
));
872 mHasGlyphRunArray
= false;
877 // mFontGroup is usually a strong reference, but refcounting is managed
878 // manually because it may be explicitly released by ReleaseFontGroup()
879 // in the case where the font group actually owns the textrun.
880 gfxFontGroup
* MOZ_OWNING_REF mFontGroup
;
882 gfxSkipChars mSkipChars
;
884 nsTextFrameUtils::Flags
885 mFlags2
; // additional flags (see also gfxShapedText::mFlags)
887 bool mDontSkipDrawing
; // true if the text run must not skip drawing, even if
888 // waiting for a user font download, e.g. because we
889 // are using it to draw canvas text
890 bool mReleasedFontGroup
; // we already called NS_RELEASE on
891 // mFontGroup, so don't do it again
892 bool mReleasedFontGroupSkippedDrawing
; // whether our old mFontGroup value
893 // was set to skip drawing
894 bool mHasGlyphRunArray
; // whether we're using an array or
895 // just storing a single glyphrun
897 // shaping state for handling variant fallback features
898 // such as subscript/superscript variant glyphs
899 ShapingState mShapingState
;
902 class gfxFontGroup final
: public gfxTextRunFactory
{
904 typedef mozilla::unicode::Script Script
;
905 typedef gfxShapedText::CompressedGlyph CompressedGlyph
;
908 Shutdown(); // platform must call this to release the languageAtomService
910 gfxFontGroup(nsPresContext
* aPresContext
,
911 const mozilla::StyleFontFamilyList
& aFontFamilyList
,
912 const gfxFontStyle
* aStyle
, nsAtom
* aLanguage
,
913 bool aExplicitLanguage
, gfxTextPerfMetrics
* aTextPerf
,
914 gfxUserFontSet
* aUserFontSet
, gfxFloat aDevToCssSize
);
916 virtual ~gfxFontGroup();
918 gfxFontGroup(const gfxFontGroup
& aOther
) = delete;
920 // Returns first valid font in the fontlist or default font.
921 // Initiates userfont loads if userfont not loaded.
922 // aGeneric: if non-null, returns the CSS generic type that was mapped to
924 gfxFont
* GetFirstValidFont(
925 uint32_t aCh
= 0x20, mozilla::StyleGenericFontFamily
* aGeneric
= nullptr);
927 // Returns the first font in the font-group that has an OpenType MATH table,
928 // or null if no such font is available. The GetMathConstant methods may be
929 // called on the returned font.
930 gfxFont
* GetFirstMathFont();
932 const gfxFontStyle
* GetStyle() const { return &mStyle
; }
935 * The listed characters should be treated as invisible and zero-width
936 * when creating textruns.
938 static bool IsInvalidChar(uint8_t ch
);
939 static bool IsInvalidChar(char16_t ch
);
942 * Make a textrun for a given string.
943 * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
944 * textrun will copy it.
945 * This calls FetchGlyphExtents on the textrun.
947 already_AddRefed
<gfxTextRun
> MakeTextRun(const char16_t
* aString
,
949 const Parameters
* aParams
,
950 mozilla::gfx::ShapedTextFlags aFlags
,
951 nsTextFrameUtils::Flags aFlags2
,
952 gfxMissingFontRecorder
* aMFR
);
954 * Make a textrun for a given string.
955 * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
956 * textrun will copy it.
957 * This calls FetchGlyphExtents on the textrun.
959 already_AddRefed
<gfxTextRun
> MakeTextRun(const uint8_t* aString
,
961 const Parameters
* aParams
,
962 mozilla::gfx::ShapedTextFlags aFlags
,
963 nsTextFrameUtils::Flags aFlags2
,
964 gfxMissingFontRecorder
* aMFR
);
967 * Textrun creation helper for clients that don't want to pass
968 * a full Parameters record.
970 template <typename T
>
971 already_AddRefed
<gfxTextRun
> MakeTextRun(const T
* aString
, uint32_t aLength
,
972 DrawTarget
* aRefDrawTarget
,
973 int32_t aAppUnitsPerDevUnit
,
974 mozilla::gfx::ShapedTextFlags aFlags
,
975 nsTextFrameUtils::Flags aFlags2
,
976 gfxMissingFontRecorder
* aMFR
) {
977 gfxTextRunFactory::Parameters params
= {
978 aRefDrawTarget
, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevUnit
};
979 return MakeTextRun(aString
, aLength
, ¶ms
, aFlags
, aFlags2
, aMFR
);
982 // Get the (possibly-cached) width of the hyphen character.
983 gfxFloat
GetHyphenWidth(const gfxTextRun::PropertyProvider
* aProvider
);
986 * Make a text run representing a single hyphen character.
987 * This will use U+2010 HYPHEN if available in the first font,
988 * otherwise fall back to U+002D HYPHEN-MINUS.
989 * The caller is responsible for deleting the returned text run
990 * when no longer required.
992 already_AddRefed
<gfxTextRun
> MakeHyphenTextRun(DrawTarget
* aDrawTarget
,
993 uint32_t aAppUnitsPerDevUnit
);
996 * Check whether a given font (specified by its gfxFontEntry)
997 * is already in the fontgroup's list of actual fonts
999 bool HasFont(const gfxFontEntry
* aFontEntry
);
1001 // This returns the preferred underline for this font group.
1002 // Some CJK fonts have wrong underline offset in its metrics.
1003 // If this group has such "bad" font, each platform's gfxFontGroup
1004 // initialized mUnderlineOffset. The value should be lower value of
1005 // first font's metrics and the bad font's metrics. Otherwise, this
1006 // returns from first font's metrics.
1007 enum { UNDERLINE_OFFSET_NOT_SET
= INT16_MAX
};
1008 gfxFloat
GetUnderlineOffset();
1010 gfxFont
* FindFontForChar(uint32_t ch
, uint32_t prevCh
, uint32_t aNextCh
,
1011 Script aRunScript
, gfxFont
* aPrevMatchedFont
,
1012 FontMatchType
* aMatchType
);
1014 gfxUserFontSet
* GetUserFontSet();
1016 // With downloadable fonts, the composition of the font group can change as
1017 // fonts are downloaded for each change in state of the user font set, the
1018 // generation value is bumped to avoid picking up previously created text runs
1019 // in the text run word cache. For font groups based on stylesheets with no
1020 // @font-face rule, this always returns 0.
1021 uint64_t GetGeneration();
1023 // generation of the latest fontset rebuild, 0 when no fontset present
1024 uint64_t GetRebuildGeneration();
1026 // used when logging text performance
1027 gfxTextPerfMetrics
* GetTextPerfMetrics() const { return mTextPerf
; }
1029 // This will call UpdateUserFonts() if the user font set is changed.
1030 void SetUserFontSet(gfxUserFontSet
* aUserFontSet
);
1032 void ClearCachedData() {
1033 mUnderlineOffset
= UNDERLINE_OFFSET_NOT_SET
;
1034 mSkipDrawing
= false;
1036 mCachedEllipsisTextRun
= nullptr;
1039 // If there is a user font set, check to see whether the font list or any
1040 // caches need updating.
1041 void UpdateUserFonts();
1043 // search for a specific userfont in the list of fonts
1044 bool ContainsUserFont(const gfxUserFontEntry
* aUserFont
);
1046 bool ShouldSkipDrawing() const { return mSkipDrawing
; }
1048 class LazyReferenceDrawTargetGetter
{
1050 virtual already_AddRefed
<DrawTarget
> GetRefDrawTarget() = 0;
1052 // The gfxFontGroup keeps ownership of this textrun.
1053 // It is only guaranteed to exist until the next call to GetEllipsisTextRun
1054 // (which might use a different appUnitsPerDev value or flags) for the font
1055 // group, or until UpdateUserFonts is called, or the fontgroup is destroyed.
1056 // Get it/use it/forget it :) - don't keep a reference that might go stale.
1057 gfxTextRun
* GetEllipsisTextRun(
1058 int32_t aAppUnitsPerDevPixel
, mozilla::gfx::ShapedTextFlags aFlags
,
1059 LazyReferenceDrawTargetGetter
& aRefDrawTargetGetter
);
1061 void CheckForUpdatedPlatformList() {
1062 auto* pfl
= gfxPlatformFontList::PlatformFontList();
1063 if (mFontListGeneration
!= pfl
->GetGeneration()) {
1064 // Forget cached fonts that may no longer be valid.
1065 mLastPrefFamily
= FontFamily();
1066 mLastPrefFont
= nullptr;
1067 mDefaultFont
= nullptr;
1073 nsAtom
* Language() const { return mLanguage
.get(); }
1076 friend class mozilla::PostTraversalTask
;
1079 TextRange(uint32_t aStart
, uint32_t aEnd
, gfxFont
* aFont
,
1080 FontMatchType aMatchType
,
1081 mozilla::gfx::ShapedTextFlags aOrientation
)
1085 matchType(aMatchType
),
1086 orientation(aOrientation
) {}
1087 uint32_t Length() const { return end
- start
; }
1088 uint32_t start
, end
;
1089 RefPtr
<gfxFont
> font
;
1090 FontMatchType matchType
;
1091 mozilla::gfx::ShapedTextFlags orientation
;
1094 // search through pref fonts for a character, return nullptr if no matching
1096 gfxFont
* WhichPrefFontSupportsChar(uint32_t aCh
, uint32_t aNextCh
,
1097 eFontPresentation aPresentation
);
1099 gfxFont
* WhichSystemFontSupportsChar(uint32_t aCh
, uint32_t aNextCh
,
1101 eFontPresentation aPresentation
);
1103 template <typename T
>
1104 void ComputeRanges(nsTArray
<TextRange
>& aRanges
, const T
* aString
,
1105 uint32_t aLength
, Script aRunScript
,
1106 mozilla::gfx::ShapedTextFlags aOrientation
);
1111 : mOwnedFamily(nullptr),
1112 mFontEntry(nullptr),
1113 mGeneric(mozilla::StyleGenericFontFamily::None
),
1114 mFontCreated(false),
1117 mCheckForFallbackFaces(false),
1118 mIsSharedFamily(false),
1119 mHasFontEntry(false) {}
1121 FamilyFace(gfxFontFamily
* aFamily
, gfxFont
* aFont
,
1122 mozilla::StyleGenericFontFamily aGeneric
)
1123 : mOwnedFamily(aFamily
),
1128 mCheckForFallbackFaces(false),
1129 mIsSharedFamily(false),
1130 mHasFontEntry(false) {
1131 NS_ASSERTION(aFont
, "font pointer must not be null");
1132 NS_ASSERTION(!aFamily
|| aFamily
->ContainsFace(aFont
->GetFontEntry()),
1133 "font is not a member of the given family");
1134 NS_IF_ADDREF(aFamily
);
1139 FamilyFace(gfxFontFamily
* aFamily
, gfxFontEntry
* aFontEntry
,
1140 mozilla::StyleGenericFontFamily aGeneric
)
1141 : mOwnedFamily(aFamily
),
1143 mFontCreated(false),
1146 mCheckForFallbackFaces(false),
1147 mIsSharedFamily(false),
1148 mHasFontEntry(true) {
1149 NS_ASSERTION(aFontEntry
, "font entry pointer must not be null");
1150 NS_ASSERTION(!aFamily
|| aFamily
->ContainsFace(aFontEntry
),
1151 "font is not a member of the given family");
1152 NS_IF_ADDREF(aFamily
);
1153 mFontEntry
= aFontEntry
;
1154 NS_ADDREF(aFontEntry
);
1157 FamilyFace(mozilla::fontlist::Family
* aFamily
, gfxFontEntry
* aFontEntry
,
1158 mozilla::StyleGenericFontFamily aGeneric
)
1159 : mSharedFamily(aFamily
),
1161 mFontCreated(false),
1164 mCheckForFallbackFaces(false),
1165 mIsSharedFamily(true),
1166 mHasFontEntry(true) {
1167 MOZ_ASSERT(aFamily
&& aFontEntry
&& aFontEntry
->mShmemFace
);
1168 mFontEntry
= aFontEntry
;
1169 NS_ADDREF(aFontEntry
);
1172 FamilyFace(const FamilyFace
& aOtherFamilyFace
)
1173 : mGeneric(aOtherFamilyFace
.mGeneric
),
1174 mFontCreated(aOtherFamilyFace
.mFontCreated
),
1175 mLoading(aOtherFamilyFace
.mLoading
),
1176 mInvalid(aOtherFamilyFace
.mInvalid
),
1177 mCheckForFallbackFaces(aOtherFamilyFace
.mCheckForFallbackFaces
),
1178 mIsSharedFamily(aOtherFamilyFace
.mIsSharedFamily
),
1179 mHasFontEntry(aOtherFamilyFace
.mHasFontEntry
) {
1180 if (mIsSharedFamily
) {
1181 mSharedFamily
= aOtherFamilyFace
.mSharedFamily
;
1183 mFont
= aOtherFamilyFace
.mFont
;
1185 } else if (mHasFontEntry
) {
1186 mFontEntry
= aOtherFamilyFace
.mFontEntry
;
1187 NS_ADDREF(mFontEntry
);
1189 mSharedFace
= aOtherFamilyFace
.mSharedFace
;
1192 mOwnedFamily
= aOtherFamilyFace
.mOwnedFamily
;
1193 NS_IF_ADDREF(mOwnedFamily
);
1195 mFont
= aOtherFamilyFace
.mFont
;
1198 mFontEntry
= aOtherFamilyFace
.mFontEntry
;
1199 NS_IF_ADDREF(mFontEntry
);
1208 if (!mIsSharedFamily
) {
1209 NS_IF_RELEASE(mOwnedFamily
);
1211 if (mHasFontEntry
) {
1212 NS_RELEASE(mFontEntry
);
1216 FamilyFace
& operator=(const FamilyFace
& aOther
) {
1220 if (!mIsSharedFamily
) {
1221 NS_IF_RELEASE(mOwnedFamily
);
1223 if (mHasFontEntry
) {
1224 NS_RELEASE(mFontEntry
);
1227 mGeneric
= aOther
.mGeneric
;
1228 mFontCreated
= aOther
.mFontCreated
;
1229 mLoading
= aOther
.mLoading
;
1230 mInvalid
= aOther
.mInvalid
;
1231 mIsSharedFamily
= aOther
.mIsSharedFamily
;
1232 mHasFontEntry
= aOther
.mHasFontEntry
;
1234 if (mIsSharedFamily
) {
1235 mSharedFamily
= aOther
.mSharedFamily
;
1237 mFont
= aOther
.mFont
;
1239 } else if (mHasFontEntry
) {
1240 mFontEntry
= aOther
.mFontEntry
;
1241 NS_ADDREF(mFontEntry
);
1243 mSharedFace
= aOther
.mSharedFace
;
1246 mOwnedFamily
= aOther
.mOwnedFamily
;
1247 NS_IF_ADDREF(mOwnedFamily
);
1249 mFont
= aOther
.mFont
;
1252 mFontEntry
= aOther
.mFontEntry
;
1253 NS_IF_ADDREF(mFontEntry
);
1260 gfxFontFamily
* OwnedFamily() const {
1261 MOZ_ASSERT(!mIsSharedFamily
);
1262 return mOwnedFamily
;
1264 mozilla::fontlist::Family
* SharedFamily() const {
1265 MOZ_ASSERT(mIsSharedFamily
);
1266 return mSharedFamily
;
1268 gfxFont
* Font() const { return mFontCreated
? mFont
: nullptr; }
1270 gfxFontEntry
* FontEntry() const {
1272 return mFont
->GetFontEntry();
1274 if (mHasFontEntry
) {
1277 if (mIsSharedFamily
) {
1278 return gfxPlatformFontList::PlatformFontList()->GetOrCreateFontEntry(
1279 mSharedFace
, SharedFamily());
1284 mozilla::StyleGenericFontFamily
Generic() const { return mGeneric
; }
1286 bool IsSharedFamily() const { return mIsSharedFamily
; }
1287 bool IsUserFontContainer() const {
1288 gfxFontEntry
* fe
= FontEntry();
1289 return fe
&& fe
->mIsUserFontContainer
;
1291 bool IsLoading() const { return mLoading
; }
1292 bool IsInvalid() const { return mInvalid
; }
1293 void CheckState(bool& aSkipDrawing
);
1294 void SetLoading(bool aIsLoading
) { mLoading
= aIsLoading
; }
1295 void SetInvalid() { mInvalid
= true; }
1296 bool CheckForFallbackFaces() const { return mCheckForFallbackFaces
; }
1297 void SetCheckForFallbackFaces() { mCheckForFallbackFaces
= true; }
1299 // Return true if we're currently loading (or waiting for) a resource that
1300 // may support the given character.
1301 bool IsLoadingFor(uint32_t aCh
) {
1305 MOZ_ASSERT(IsUserFontContainer());
1306 auto* ufe
= static_cast<gfxUserFontEntry
*>(FontEntry());
1307 return ufe
&& ufe
->CharacterInUnicodeRange(aCh
);
1310 void SetFont(gfxFont
* aFont
) {
1311 NS_ASSERTION(aFont
, "font pointer must not be null");
1315 } else if (mHasFontEntry
) {
1316 NS_RELEASE(mFontEntry
);
1317 mHasFontEntry
= false;
1320 mFontCreated
= true;
1324 bool EqualsUserFont(const gfxUserFontEntry
* aUserFont
) const;
1328 gfxFontFamily
* MOZ_OWNING_REF mOwnedFamily
;
1329 mozilla::fontlist::Family
* MOZ_NON_OWNING_REF mSharedFamily
;
1331 // either a font or a font entry exists
1333 // Whichever of these fields is actually present will be a strong
1334 // reference, with refcounting handled manually.
1335 gfxFont
* MOZ_OWNING_REF mFont
;
1336 gfxFontEntry
* MOZ_OWNING_REF mFontEntry
;
1337 mozilla::fontlist::Face
* MOZ_NON_OWNING_REF mSharedFace
;
1339 mozilla::StyleGenericFontFamily mGeneric
;
1340 bool mFontCreated
: 1;
1343 bool mCheckForFallbackFaces
: 1;
1344 bool mIsSharedFamily
: 1;
1345 bool mHasFontEntry
: 1;
1348 nsPresContext
* mPresContext
= nullptr;
1350 // List of font families, either named or generic.
1351 // Generic names map to system pref fonts based on language.
1352 mozilla::StyleFontFamilyList mFamilyList
;
1354 // Fontlist containing a font entry for each family found. gfxFont objects
1355 // are created as needed and userfont loads are initiated when needed.
1356 // Code should be careful about addressing this array directly.
1357 nsTArray
<FamilyFace
> mFonts
;
1359 RefPtr
<gfxFont
> mDefaultFont
;
1360 gfxFontStyle mStyle
;
1362 RefPtr
<nsAtom
> mLanguage
;
1364 gfxFloat mUnderlineOffset
;
1365 gfxFloat mHyphenWidth
;
1366 gfxFloat mDevToCssSize
;
1368 RefPtr
<gfxUserFontSet
> mUserFontSet
;
1369 uint64_t mCurrGeneration
; // track the current user font set generation,
1370 // rebuild font list if needed
1372 gfxTextPerfMetrics
* mTextPerf
;
1374 // Cache a textrun representing an ellipsis (useful for CSS text-overflow)
1375 // at a specific appUnitsPerDevPixel size and orientation
1376 RefPtr
<gfxTextRun
> mCachedEllipsisTextRun
;
1378 // cache the most recent pref font to avoid general pref font lookup
1379 FontFamily mLastPrefFamily
;
1380 RefPtr
<gfxFont
> mLastPrefFont
;
1381 eFontPrefLang mLastPrefLang
; // lang group for last pref font
1382 eFontPrefLang mPageLang
;
1383 bool mLastPrefFirstFont
; // is this the first font in the list of pref fonts
1384 // for this lang group?
1386 bool mSkipDrawing
; // hide text while waiting for a font
1387 // download to complete (or fallback
1390 bool mExplicitLanguage
; // Does mLanguage come from an explicit attribute?
1392 // Generic font family used to select among font prefs during fallback.
1393 mozilla::StyleGenericFontFamily mFallbackGeneric
=
1394 mozilla::StyleGenericFontFamily::None
;
1396 uint32_t mFontListGeneration
= 0; // platform font list generation for this
1400 * Textrun creation short-cuts for special cases where we don't need to
1401 * call a font shaper to generate glyphs.
1403 already_AddRefed
<gfxTextRun
> MakeEmptyTextRun(
1404 const Parameters
* aParams
, mozilla::gfx::ShapedTextFlags aFlags
,
1405 nsTextFrameUtils::Flags aFlags2
);
1407 already_AddRefed
<gfxTextRun
> MakeSpaceTextRun(
1408 const Parameters
* aParams
, mozilla::gfx::ShapedTextFlags aFlags
,
1409 nsTextFrameUtils::Flags aFlags2
);
1411 template <typename T
>
1412 already_AddRefed
<gfxTextRun
> MakeBlankTextRun(
1413 const T
* aString
, uint32_t aLength
, const Parameters
* aParams
,
1414 mozilla::gfx::ShapedTextFlags aFlags
, nsTextFrameUtils::Flags aFlags2
);
1416 // Initialize the list of fonts
1417 void BuildFontList();
1419 // Get the font at index i within the fontlist, for character aCh (in case
1420 // of fonts with multiple resources and unicode-range partitioning).
1421 // Will initiate userfont load if not already loaded.
1422 // May return null if userfont not loaded or if font invalid.
1423 // If *aLoading is true, a relevant resource is already being loaded so no
1424 // new download will be initiated; if a download is started, *aLoading will
1425 // be set to true on return.
1426 gfxFont
* GetFontAt(int32_t i
, uint32_t aCh
, bool* aLoading
);
1428 // Simplified version of GetFontAt() for use where we just need a font for
1429 // metrics, math layout tables, etc.
1430 gfxFont
* GetFontAt(int32_t i
, uint32_t aCh
= 0x20) {
1431 bool loading
= false;
1432 return GetFontAt(i
, aCh
, &loading
);
1435 // will always return a font or force a shutdown
1436 gfxFont
* GetDefaultFont();
1438 // Init this font group's font metrics. If there no bad fonts, you don't need
1439 // to call this. But if there are one or more bad fonts which have bad
1440 // underline offset, you should call this with the *first* bad font.
1441 void InitMetricsForBadFont(gfxFont
* aBadFont
);
1443 // Set up the textrun glyphs for an entire text run:
1444 // find script runs, and then call InitScriptRun for each
1445 template <typename T
>
1446 void InitTextRun(DrawTarget
* aDrawTarget
, gfxTextRun
* aTextRun
,
1447 const T
* aString
, uint32_t aLength
,
1448 gfxMissingFontRecorder
* aMFR
);
1450 // InitTextRun helper to handle a single script run, by finding font ranges
1451 // and calling each font's InitTextRun() as appropriate
1452 template <typename T
>
1453 void InitScriptRun(DrawTarget
* aDrawTarget
, gfxTextRun
* aTextRun
,
1454 const T
* aString
, uint32_t aScriptRunStart
,
1455 uint32_t aScriptRunEnd
, Script aRunScript
,
1456 gfxMissingFontRecorder
* aMFR
);
1458 // Helper for font-matching:
1459 // search all faces in a family for a fallback in cases where it's unclear
1460 // whether the family might have a font for a given character
1461 gfxFont
* FindFallbackFaceForChar(const FamilyFace
& aFamily
, uint32_t aCh
,
1463 eFontPresentation aPresentation
);
1465 gfxFont
* FindFallbackFaceForChar(mozilla::fontlist::Family
* aFamily
,
1466 uint32_t aCh
, uint32_t aNextCh
,
1467 eFontPresentation aPresentation
);
1469 gfxFont
* FindFallbackFaceForChar(gfxFontFamily
* aFamily
, uint32_t aCh
,
1471 eFontPresentation aPresentation
);
1473 // helper methods for looking up fonts
1475 // lookup and add a font with a given name (i.e. *not* a generic!)
1476 void AddPlatformFont(const nsACString
& aName
, bool aQuotedName
,
1477 nsTArray
<FamilyAndGeneric
>& aFamilyList
);
1479 // do style selection and add entries to list
1480 void AddFamilyToFontList(gfxFontFamily
* aFamily
,
1481 mozilla::StyleGenericFontFamily aGeneric
);
1482 void AddFamilyToFontList(mozilla::fontlist::Family
* aFamily
,
1483 mozilla::StyleGenericFontFamily aGeneric
);
1486 // A "missing font recorder" is to be used during text-run creation to keep
1487 // a record of any scripts encountered for which font coverage was lacking;
1488 // when Flush() is called, it sends a notification that front-end code can use
1489 // to download fonts on demand (or whatever else it wants to do).
1491 #define GFX_MISSING_FONTS_NOTIFY_PREF "gfx.missing_fonts.notify"
1493 class gfxMissingFontRecorder
{
1495 gfxMissingFontRecorder() {
1496 MOZ_COUNT_CTOR(gfxMissingFontRecorder
);
1497 memset(&mMissingFonts
, 0, sizeof(mMissingFonts
));
1500 ~gfxMissingFontRecorder() {
1502 for (uint32_t i
= 0; i
< kNumScriptBitsWords
; i
++) {
1503 NS_ASSERTION(mMissingFonts
[i
] == 0,
1504 "failed to flush the missing-font recorder");
1507 MOZ_COUNT_DTOR(gfxMissingFontRecorder
);
1510 // record this script code in our mMissingFonts bitset
1511 void RecordScript(mozilla::unicode::Script aScriptCode
) {
1512 mMissingFonts
[static_cast<uint32_t>(aScriptCode
) >> 5] |=
1513 (1 << (static_cast<uint32_t>(aScriptCode
) & 0x1f));
1516 // send a notification of any missing-scripts that have been
1517 // recorded, and clear the mMissingFonts set for re-use
1520 // forget any missing-scripts that have been recorded up to now;
1521 // called before discarding a recorder we no longer care about
1522 void Clear() { memset(&mMissingFonts
, 0, sizeof(mMissingFonts
)); }
1525 // Number of 32-bit words needed for the missing-script flags
1526 static const uint32_t kNumScriptBitsWords
=
1527 ((static_cast<int>(mozilla::unicode::Script::NUM_SCRIPT_CODES
) + 31) /
1529 uint32_t mMissingFonts
[kNumScriptBitsWords
];