1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Foundation code.
17 * The Initial Developer of the Original Code is Mozilla Foundation.
18 * Portions created by the Initial Developer are Copyright (C) 2005-2009
19 * the Initial Developer. All Rights Reserved.
22 * Stuart Parmenter <stuart@mozilla.com>
23 * Masayuki Nakano <masayuki@d-toybox.com>
24 * John Daggett <jdaggett@mozilla.com>
25 * Jonathan Kew <jfkthame@gmail.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
48 #include "gfxFontUtils.h"
50 #include "nsTHashtable.h"
51 #include "nsHashKeys.h"
52 #include "gfxSkipChars.h"
54 #include "nsExpirationTracker.h"
55 #include "gfxFontConstants.h"
56 #include "gfxPlatform.h"
58 #include "nsISupportsImpl.h"
70 class gfxUserFontData
;
72 class nsILanguageAtomService
;
74 typedef struct _hb_blob_t hb_blob_t
;
76 // We should eliminate these synonyms when it won't cause many merge conflicts.
77 #define FONT_STYLE_NORMAL NS_FONT_STYLE_NORMAL
78 #define FONT_STYLE_ITALIC NS_FONT_STYLE_ITALIC
79 #define FONT_STYLE_OBLIQUE NS_FONT_STYLE_OBLIQUE
81 // We should eliminate these synonyms when it won't cause many merge conflicts.
82 #define FONT_WEIGHT_NORMAL NS_FONT_WEIGHT_NORMAL
83 #define FONT_WEIGHT_BOLD NS_FONT_WEIGHT_BOLD
85 #define FONT_MAX_SIZE 2000.0
87 #define NO_FONT_LANGUAGE_OVERRIDE 0
89 // An OpenType feature tag and value pair
90 struct THEBES_API gfxFontFeature
{
91 PRUint32 mTag
; // see http://www.microsoft.com/typography/otspec/featuretags.htm
92 PRUint32 mValue
; // 0 = off, 1 = on, larger values may be used as parameters
93 // to features that select among multiple alternatives
97 operator<(const gfxFontFeature
& a
, const gfxFontFeature
& b
)
99 return (a
.mTag
< b
.mTag
) || ((a
.mTag
== b
.mTag
) && (a
.mValue
< b
.mValue
));
103 operator==(const gfxFontFeature
& a
, const gfxFontFeature
& b
)
105 return (a
.mTag
== b
.mTag
) && (a
.mValue
== b
.mValue
);
109 struct THEBES_API gfxFontStyle
{
111 gfxFontStyle(PRUint8 aStyle
, PRUint16 aWeight
, PRInt16 aStretch
,
112 gfxFloat aSize
, nsIAtom
*aLanguage
,
113 float aSizeAdjust
, PRPackedBool aSystemFont
,
114 PRPackedBool aFamilyNameQuirks
,
115 PRPackedBool aPrinterFont
,
116 const nsString
& aFeatureSettings
,
117 const nsString
& aLanguageOverride
);
118 gfxFontStyle(const gfxFontStyle
& aStyle
);
120 // The style of font (normal, italic, oblique)
123 // Say that this font is a system font and therefore does not
124 // require certain fixup that we do for fonts from untrusted
126 PRPackedBool systemFont
: 1;
128 // Say that this font is used for print or print preview.
129 PRPackedBool printerFont
: 1;
131 // True if the character set quirks (for treatment of "Symbol",
132 // "Wingdings", etc.) should be applied.
133 PRPackedBool familyNameQuirks
: 1;
135 // The weight of the font: 100, 200, ... 900.
138 // The stretch of the font (the sum of various NS_FONT_STRETCH_*
139 // constants; see gfxFontConstants.h).
142 // The logical size of the font, in pixels
145 // The aspect-value (ie., the ratio actualsize:actualxheight) that any
146 // actual physical font created from this font structure must have when
147 // rendering or measuring a string. A value of 0 means no adjustment
151 // the language (may be an internal langGroup code rather than an actual
152 // language code) specified in the document or element's lang property,
153 // or inferred from the charset
154 nsRefPtr
<nsIAtom
> language
;
156 // Language system tag, to override document language;
157 // an OpenType "language system" tag represented as a 32-bit integer
158 // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
159 // Normally 0, so font rendering will use the document or element language
160 // (see above) to control any language-specific rendering, but the author
161 // can override this for cases where the options implemented in the font
162 // do not directly match the actual language. (E.g. lang may be Macedonian,
163 // but the font in use does not explicitly support this; the author can
164 // use font-language-override to request the Serbian option in the font
165 // in order to get correct glyph shapes.)
166 PRUint32 languageOverride
;
168 // custom opentype feature settings
169 nsTArray
<gfxFontFeature
> featureSettings
;
171 // Return the final adjusted font size for the given aspect ratio.
172 // Not meant to be called when sizeAdjust = 0.
173 gfxFloat
GetAdjustedSize(gfxFloat aspect
) const {
174 NS_ASSERTION(sizeAdjust
!= 0.0, "Not meant to be called when sizeAdjust = 0");
175 gfxFloat adjustedSize
= PR_MAX(NS_round(size
*(sizeAdjust
/aspect
)), 1.0);
176 return PR_MIN(adjustedSize
, FONT_MAX_SIZE
);
179 PLDHashNumber
Hash() const {
180 return ((style
+ (systemFont
<< 7) + (familyNameQuirks
<< 8) +
181 (weight
<< 9)) + PRUint32(size
*1000) + PRUint32(sizeAdjust
*1000)) ^
182 nsISupportsHashKey::HashKey(language
);
185 PRInt8
ComputeWeight() const;
187 PRBool
Equals(const gfxFontStyle
& other
) const {
188 return (size
== other
.size
) &&
189 (style
== other
.style
) &&
190 (systemFont
== other
.systemFont
) &&
191 (printerFont
== other
.printerFont
) &&
192 (familyNameQuirks
== other
.familyNameQuirks
) &&
193 (weight
== other
.weight
) &&
194 (stretch
== other
.stretch
) &&
195 (language
== other
.language
) &&
196 (sizeAdjust
== other
.sizeAdjust
) &&
197 (featureSettings
== other
.featureSettings
) &&
198 (languageOverride
== other
.languageOverride
);
201 static void ParseFontFeatureSettings(const nsString
& aFeatureString
,
202 nsTArray
<gfxFontFeature
>& aFeatures
);
204 static PRUint32
ParseFontLanguageOverride(const nsString
& aLangTag
);
209 NS_INLINE_DECL_REFCOUNTING(gfxFontEntry
)
211 gfxFontEntry(const nsAString
& aName
, gfxFontFamily
*aFamily
= nsnull
,
212 PRBool aIsStandardFace
= PR_FALSE
) :
213 mName(aName
), mItalic(PR_FALSE
), mFixedPitch(PR_FALSE
),
214 mIsProxy(PR_FALSE
), mIsValid(PR_TRUE
),
215 mIsBadUnderlineFont(PR_FALSE
), mIsUserFont(PR_FALSE
),
216 mIsLocalUserFont(PR_FALSE
), mStandardFace(aIsStandardFace
),
217 mSymbolFont(PR_FALSE
),
218 mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL
),
219 mHasCmapTable(PR_FALSE
),
220 mCmapInitialized(PR_FALSE
),
221 mUVSOffset(0), mUVSData(nsnull
),
222 mUserFontData(nsnull
),
223 mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE
),
227 virtual ~gfxFontEntry();
229 // unique name for the face, *not* the family
230 const nsString
& Name() const { return mName
; }
232 PRUint16
Weight() const { return mWeight
; }
233 PRInt16
Stretch() const { return mStretch
; }
235 PRBool
IsUserFont() const { return mIsUserFont
; }
236 PRBool
IsLocalUserFont() const { return mIsLocalUserFont
; }
237 PRBool
IsFixedPitch() const { return mFixedPitch
; }
238 PRBool
IsItalic() const { return mItalic
; }
239 PRBool
IsBold() const { return mWeight
>= 600; } // bold == weights 600 and above
240 PRBool
IsSymbolFont() const { return mSymbolFont
; }
242 inline PRBool
HasCmapTable() {
243 if (!mCmapInitialized
) {
246 return mHasCmapTable
;
249 inline PRBool
HasCharacter(PRUint32 ch
) {
250 if (mCharacterMap
.test(ch
))
253 return TestCharacterMap(ch
);
256 virtual PRBool
SkipDuringSystemFallback() { return PR_FALSE
; }
257 virtual PRBool
TestCharacterMap(PRUint32 aCh
);
258 nsresult
InitializeUVSMap();
259 PRUint16
GetUVSGlyph(PRUint32 aCh
, PRUint32 aVS
);
260 virtual nsresult
ReadCMAP();
262 virtual PRBool
MatchesGenericFamily(const nsACString
& aGeneric
) const {
265 virtual PRBool
SupportsLangGroup(nsIAtom
*aLangGroup
) const {
269 virtual nsresult
GetFontTable(PRUint32 aTableTag
, FallibleTArray
<PRUint8
>& aBuffer
) {
270 return NS_ERROR_FAILURE
; // all platform subclasses should reimplement this!
273 void SetFamily(gfxFontFamily
* aFamily
) {
277 const nsString
& FamilyName() const;
279 already_AddRefed
<gfxFont
> FindOrMakeFont(const gfxFontStyle
*aStyle
,
282 // Get an existing font table cache entry in aBlob if it has been
283 // registered, or return PR_FALSE if not. Callers must call
284 // hb_blob_destroy on aBlob if PR_TRUE is returned.
286 // Note that some gfxFont implementations may not call this at all,
287 // if it is more efficient to get the table from the OS at that level.
288 PRBool
GetExistingFontTable(PRUint32 aTag
, hb_blob_t
** aBlob
);
290 // Elements of aTable are transferred (not copied) to and returned in a
291 // new hb_blob_t which is registered on the gfxFontEntry, but the initial
292 // reference is owned by the caller. Removing the last reference
293 // unregisters the table from the font entry.
295 // Pass NULL for aBuffer to indicate that the table is not present and
296 // NULL will be returned. Also returns NULL on OOM.
297 hb_blob_t
*ShareFontTableAndGetBlob(PRUint32 aTag
,
298 FallibleTArray
<PRUint8
>* aTable
);
300 // Preload a font table into the cache (used to store layout tables for
301 // harfbuzz, when they will be stripped from the actual sfnt being
302 // passed to platform font APIs for rasterization)
303 void PreloadFontTable(PRUint32 aTag
, FallibleTArray
<PRUint8
>& aTable
);
307 PRPackedBool mItalic
: 1;
308 PRPackedBool mFixedPitch
: 1;
309 PRPackedBool mIsProxy
: 1;
310 PRPackedBool mIsValid
: 1;
311 PRPackedBool mIsBadUnderlineFont
: 1;
312 PRPackedBool mIsUserFont
: 1;
313 PRPackedBool mIsLocalUserFont
: 1;
314 PRPackedBool mStandardFace
: 1;
315 PRPackedBool mSymbolFont
: 1;
320 PRPackedBool mHasCmapTable
;
321 PRPackedBool mCmapInitialized
;
322 gfxSparseBitSet mCharacterMap
;
324 nsAutoArrayPtr
<PRUint8
> mUVSData
;
325 gfxUserFontData
* mUserFontData
;
327 nsTArray
<gfxFontFeature
> mFeatureSettings
;
328 PRUint32 mLanguageOverride
;
331 friend class gfxPlatformFontList
;
332 friend class gfxMacPlatformFontList
;
333 friend class gfxUserFcFontEntry
;
334 friend class gfxFontFamily
;
335 friend class gfxSingleFaceMacFontFamily
;
338 mItalic(PR_FALSE
), mFixedPitch(PR_FALSE
),
339 mIsProxy(PR_FALSE
), mIsValid(PR_TRUE
),
340 mIsBadUnderlineFont(PR_FALSE
),
341 mIsUserFont(PR_FALSE
),
342 mIsLocalUserFont(PR_FALSE
),
343 mStandardFace(PR_FALSE
),
344 mSymbolFont(PR_FALSE
),
345 mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL
),
346 mHasCmapTable(PR_FALSE
),
347 mCmapInitialized(PR_FALSE
),
348 mUVSOffset(0), mUVSData(nsnull
),
349 mUserFontData(nsnull
),
350 mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE
),
354 virtual gfxFont
*CreateFontInstance(const gfxFontStyle
*aFontStyle
, PRBool aNeedsBold
) {
355 NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
359 gfxFontFamily
*mFamily
;
364 * Font table hashtable, to support GetFontTable for harfbuzz.
366 * The harfbuzz shaper (and potentially other clients) needs access to raw
367 * font table data. This needs to be cached so that it can be used
368 * repeatedly (each time we construct a text run; in some cases, for
369 * each character/glyph within the run) without re-fetching large tables
372 * Because we may instantiate many gfxFonts for the same physical font
373 * file (at different sizes), we should ensure that they can share a
374 * single cached copy of the font tables. To do this, we implement table
375 * access and sharing on the fontEntry rather than the font itself.
377 * The default implementation uses GetFontTable() to read font table
378 * data into byte arrays, and wraps them in blobs which are registered in
379 * a hashtable. The hashtable can then return pre-existing blobs to
382 * Harfbuzz will "destroy" the blobs when it is finished with them. When
383 * the last blob reference is removed, the FontTableBlobData user data
384 * will remove the blob from the hashtable if still registered.
387 class FontTableBlobData
;
390 * FontTableHashEntry manages the entries of hb_blob_ts for two
391 * different situations:
393 * The common situation is to share font table across fonts with the same
394 * font entry (but different sizes) for use by HarfBuzz. The hashtable
395 * does not own a strong reference to the blob, but keeps a weak pointer,
396 * managed by FontTableBlobData. Similarly FontTableBlobData keeps only a
397 * weak pointer to the hashtable, managed by FontTableHashEntry.
399 * Some font tables are saved here before they would get stripped by OTS
400 * sanitizing. These are retained for harfbuzz, which does its own
401 * sanitizing. The hashtable owns a reference, so ownership is simple.
404 class FontTableHashEntry
: public nsUint32HashKey
407 // Declarations for nsTHashtable
409 typedef nsUint32HashKey KeyClass
;
410 typedef KeyClass::KeyType KeyType
;
411 typedef KeyClass::KeyTypePointer KeyTypePointer
;
413 FontTableHashEntry(KeyTypePointer aTag
)
414 : KeyClass(aTag
), mBlob() { };
415 // Copying transfers blob association.
416 FontTableHashEntry(FontTableHashEntry
& toCopy
)
417 : KeyClass(toCopy
), mBlob(toCopy
.mBlob
)
419 toCopy
.mBlob
= nsnull
;
422 ~FontTableHashEntry() { Clear(); }
424 // FontTable/Blob API
426 // Transfer (not copy) elements of aTable to a new hb_blob_t and
427 // return ownership to the caller. A weak reference to the blob is
428 // recorded in the hashtable entry so that others may use the same
431 ShareTableAndGetBlob(FallibleTArray
<PRUint8
>& aTable
,
432 nsTHashtable
<FontTableHashEntry
> *aHashtable
);
434 // Transfer (not copy) elements of aTable to a new hb_blob_t that is
435 // owned by the hashtable entry.
436 void SaveTable(FallibleTArray
<PRUint8
>& aTable
);
438 // Return a strong reference to the blob.
439 // Callers must hb_blob_destroy the returned blob.
440 hb_blob_t
*GetBlob() const;
445 static void DeleteFontTableBlobData(void *aBlobData
);
447 FontTableHashEntry
& operator=(FontTableHashEntry
& toCopy
);
449 FontTableBlobData
*mSharedBlobData
;
453 nsTHashtable
<FontTableHashEntry
> mFontTableCache
;
455 gfxFontEntry(const gfxFontEntry
&);
456 gfxFontEntry
& operator=(const gfxFontEntry
&);
460 // used when picking fallback font
462 FontSearch(const PRUint32 aCharacter
, gfxFont
*aFont
) :
463 mCh(aCharacter
), mFontToMatch(aFont
), mMatchRank(0), mCount(0) {
466 gfxFont
* mFontToMatch
;
468 nsRefPtr
<gfxFontEntry
> mBestMatch
;
472 class gfxFontFamily
{
474 NS_INLINE_DECL_REFCOUNTING(gfxFontFamily
)
476 gfxFontFamily(const nsAString
& aName
) :
478 mOtherFamilyNamesInitialized(PR_FALSE
),
479 mHasOtherFamilyNames(PR_FALSE
),
480 mFaceNamesInitialized(PR_FALSE
),
481 mHasStyles(PR_FALSE
),
482 mIsSimpleFamily(PR_FALSE
),
483 mIsBadUnderlineFamily(PR_FALSE
)
486 virtual ~gfxFontFamily() { }
488 const nsString
& Name() { return mName
; }
490 virtual void LocalizedName(nsAString
& aLocalizedName
);
491 virtual PRBool
HasOtherFamilyNames();
493 nsTArray
<nsRefPtr
<gfxFontEntry
> >& GetFontList() { return mAvailableFonts
; }
495 void AddFontEntry(nsRefPtr
<gfxFontEntry
> aFontEntry
) {
496 mAvailableFonts
.AppendElement(aFontEntry
);
497 aFontEntry
->SetFamily(this);
500 // note that the styles for this family have been added
501 void SetHasStyles(PRBool aHasStyles
) { mHasStyles
= aHasStyles
; }
503 // choose a specific face to match a style using CSS font matching
504 // rules (weight matching occurs here). may return a face that doesn't
505 // precisely match (e.g. normal face when no italic face exists).
506 // aNeedsSyntheticBold is set to true when synthetic bolding is
507 // needed, false otherwise
508 gfxFontEntry
*FindFontForStyle(const gfxFontStyle
& aFontStyle
,
509 PRBool
& aNeedsSyntheticBold
);
511 // iterates over faces looking for a match with a given characters
512 // used as part of the font fallback process
513 void FindFontForChar(FontSearch
*aMatchData
);
515 // read in other family names, if any, and use functor to add each into cache
516 virtual void ReadOtherFamilyNames(gfxPlatformFontList
*aPlatformFontList
);
518 // set when other family names have been read in
519 void SetOtherFamilyNamesInitialized() {
520 mOtherFamilyNamesInitialized
= PR_TRUE
;
523 // read in other localized family names, fullnames and Postscript names
524 // for all faces and append to lookup tables
525 virtual void ReadFaceNames(gfxPlatformFontList
*aPlatformFontList
,
526 PRBool aNeedFullnamePostscriptNames
);
528 // find faces belonging to this family (platform implementations override this;
529 // should be made pure virtual once all subclasses have been updated)
530 virtual void FindStyleVariations() { }
532 // search for a specific face using the Postscript name
533 gfxFontEntry
* FindFont(const nsAString
& aPostscriptName
);
535 // read in cmaps for all the faces
537 PRUint32 i
, numFonts
= mAvailableFonts
.Length();
538 // called from RunLoader BEFORE CheckForSimpleFamily so that there cannot
539 // be any NULL entries in mAvailableFonts
540 for (i
= 0; i
< numFonts
; i
++)
541 mAvailableFonts
[i
]->ReadCMAP();
544 // mark this family as being in the "bad" underline offset blacklist
545 void SetBadUnderlineFamily() {
546 mIsBadUnderlineFamily
= PR_TRUE
;
548 SetBadUnderlineFonts();
552 PRBool
IsBadUnderlineFamily() const { return mIsBadUnderlineFamily
; }
554 // sort available fonts to put preferred (standard) faces towards the end
555 void SortAvailableFonts();
557 // check whether the family fits into the simple 4-face model,
558 // so we can use simplified style-matching;
559 // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
560 void CheckForSimpleFamily();
563 // fills in an array with weights of faces that match style,
564 // returns whether any matching entries found
565 virtual PRBool
FindWeightsForStyle(gfxFontEntry
* aFontsForWeights
[],
566 PRBool anItalic
, PRInt16 aStretch
);
568 PRBool
ReadOtherFamilyNamesForFace(gfxPlatformFontList
*aPlatformFontList
,
569 FallibleTArray
<PRUint8
>& aNameTable
,
570 PRBool useFullName
= PR_FALSE
);
572 // set whether this font family is in "bad" underline offset blacklist.
573 void SetBadUnderlineFonts() {
574 PRUint32 i
, numFonts
= mAvailableFonts
.Length();
575 for (i
= 0; i
< numFonts
; i
++) {
576 if (mAvailableFonts
[i
]) {
577 mAvailableFonts
[i
]->mIsBadUnderlineFont
= PR_TRUE
;
583 nsTArray
<nsRefPtr
<gfxFontEntry
> > mAvailableFonts
;
584 PRPackedBool mOtherFamilyNamesInitialized
;
585 PRPackedBool mHasOtherFamilyNames
;
586 PRPackedBool mFaceNamesInitialized
;
587 PRPackedBool mHasStyles
;
588 PRPackedBool mIsSimpleFamily
;
589 PRPackedBool mIsBadUnderlineFamily
;
592 // for "simple" families, the faces are stored in mAvailableFonts
593 // with fixed positions:
594 kRegularFaceIndex
= 0,
596 kItalicFaceIndex
= 2,
597 kBoldItalicFaceIndex
= 3,
598 // mask values for selecting face with bold and/or italic attributes
604 struct gfxTextRange
{
605 gfxTextRange(PRUint32 aStart
, PRUint32 aEnd
) : start(aStart
), end(aEnd
) { }
606 PRUint32
Length() const { return end
- start
; }
607 nsRefPtr
<gfxFont
> font
;
615 * The mFonts hashtable contains most fonts, indexed by (gfxFontEntry*, style).
616 * It does not add a reference to the fonts it contains.
617 * When a font's refcount decreases to zero, instead of deleting it we
618 * add it to our expiration tracker.
619 * The expiration tracker tracks fonts with zero refcount. After a certain
620 * period of time, such fonts expire and are deleted.
622 * We're using 3 generations with a ten-second generation interval, so
623 * zero-refcount fonts will be deleted 20-30 seconds after their refcount
624 * goes to zero, if timer events fire in a timely manner.
626 class THEBES_API gfxFontCache
: public nsExpirationTracker
<gfxFont
,3> {
628 enum { TIMEOUT_SECONDS
= 10 };
630 : nsExpirationTracker
<gfxFont
,3>(TIMEOUT_SECONDS
*1000) { mFonts
.Init(); }
632 // Expire everything that has a zero refcount, so we don't leak them.
634 // All fonts should be gone.
635 NS_WARN_IF_FALSE(mFonts
.Count() == 0,
636 "Fonts still alive while shutting down gfxFontCache");
637 // Note that we have to delete everything through the expiration
638 // tracker, since there might be fonts not in the hashtable but in
643 * Get the global gfxFontCache. You must call Init() before
644 * calling this method --- the result will not be null.
646 static gfxFontCache
* GetCache() {
650 static nsresult
Init();
651 // It's OK to call this even if Init() has not been called.
652 static void Shutdown();
654 // Look up a font in the cache. Returns an addrefed pointer, or null
655 // if there's nothing matching in the cache
656 already_AddRefed
<gfxFont
> Lookup(const gfxFontEntry
*aFontEntry
,
657 const gfxFontStyle
*aFontGroup
);
658 // We created a new font (presumably because Lookup returned null);
659 // put it in the cache. The font's refcount should be nonzero. It is
660 // allowable to add a new font even if there is one already in the
661 // cache with the same key; we'll forget about the old one.
662 void AddNew(gfxFont
*aFont
);
664 // The font's refcount has gone to zero; give ownership of it to
665 // the cache. We delete it if it's not acquired again after a certain
667 void NotifyReleased(gfxFont
*aFont
);
669 // This gets called when the timeout has expired on a zero-refcount
670 // font; we just delete it.
671 virtual void NotifyExpired(gfxFont
*aFont
);
673 // Cleans out the hashtable and removes expired fonts waiting for cleanup.
674 // Other gfxFont objects may be still in use but they will be pushed
675 // into the expiration queues and removed.
682 void DestroyFont(gfxFont
*aFont
);
684 static gfxFontCache
*gGlobalCache
;
687 const gfxFontEntry
* mFontEntry
;
688 const gfxFontStyle
* mStyle
;
689 Key(const gfxFontEntry
* aFontEntry
, const gfxFontStyle
* aStyle
)
690 : mFontEntry(aFontEntry
), mStyle(aStyle
) {}
693 class HashEntry
: public PLDHashEntryHdr
{
695 typedef const Key
& KeyType
;
696 typedef const Key
* KeyTypePointer
;
698 // When constructing a new entry in the hashtable, we'll leave this
699 // blank. The caller of Put() will fill this in.
700 HashEntry(KeyTypePointer aStr
) : mFont(nsnull
) { }
701 HashEntry(const HashEntry
& toCopy
) : mFont(toCopy
.mFont
) { }
704 PRBool
KeyEquals(const KeyTypePointer aKey
) const;
705 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
706 static PLDHashNumber
HashKey(const KeyTypePointer aKey
) {
707 return NS_PTR_TO_INT32(aKey
->mFontEntry
) ^ aKey
->mStyle
->Hash();
709 enum { ALLOW_MEMMOVE
= PR_TRUE
};
714 nsTHashtable
<HashEntry
> mFonts
;
718 * This stores glyph bounds information for a particular gfxFont, at
719 * a particular appunits-per-dev-pixel ratio (because the compressed glyph
720 * width array is stored in appunits).
722 * We store a hashtable from glyph IDs to float bounding rects. For the
723 * common case where the glyph has no horizontal left bearing, and no
724 * y overflow above the font ascent or below the font descent, and tight
725 * bounding boxes are not required, we avoid storing the glyph ID in the hashtable
726 * and instead consult an array of 16-bit glyph XMost values (in appunits).
727 * This array always has an entry for the font's space glyph --- the width is
728 * assumed to be zero.
730 class THEBES_API gfxGlyphExtents
{
732 gfxGlyphExtents(PRUint32 aAppUnitsPerDevUnit
) :
733 mAppUnitsPerDevUnit(aAppUnitsPerDevUnit
) {
734 MOZ_COUNT_CTOR(gfxGlyphExtents
);
735 mTightGlyphExtents
.Init();
739 enum { INVALID_WIDTH
= 0xFFFF };
741 // returns INVALID_WIDTH => not a contained glyph
742 // Otherwise the glyph has no before-bearing or vertical bearings,
743 // and the result is its width measured from the baseline origin, in
745 PRUint16
GetContainedGlyphWidthAppUnits(PRUint32 aGlyphID
) const {
746 return mContainedGlyphWidths
.Get(aGlyphID
);
749 PRBool
IsGlyphKnown(PRUint32 aGlyphID
) const {
750 return mContainedGlyphWidths
.Get(aGlyphID
) != INVALID_WIDTH
||
751 mTightGlyphExtents
.GetEntry(aGlyphID
) != nsnull
;
754 PRBool
IsGlyphKnownWithTightExtents(PRUint32 aGlyphID
) const {
755 return mTightGlyphExtents
.GetEntry(aGlyphID
) != nsnull
;
758 // Get glyph extents; a rectangle relative to the left baseline origin
759 // Returns true on success. Can fail on OOM or when aContext is null
760 // and extents were not (successfully) prefetched.
761 PRBool
GetTightGlyphExtentsAppUnits(gfxFont
*aFont
, gfxContext
*aContext
,
762 PRUint32 aGlyphID
, gfxRect
*aExtents
);
764 void SetContainedGlyphWidthAppUnits(PRUint32 aGlyphID
, PRUint16 aWidth
) {
765 mContainedGlyphWidths
.Set(aGlyphID
, aWidth
);
767 void SetTightGlyphExtents(PRUint32 aGlyphID
, const gfxRect
& aExtentsAppUnits
);
769 PRUint32
GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit
; }
772 class HashEntry
: public nsUint32HashKey
{
774 // When constructing a new entry in the hashtable, we'll leave this
775 // blank. The caller of Put() will fill this in.
776 HashEntry(KeyTypePointer aPtr
) : nsUint32HashKey(aPtr
) {}
777 HashEntry(const HashEntry
& toCopy
) : nsUint32HashKey(toCopy
) {
778 x
= toCopy
.x
; y
= toCopy
.y
; width
= toCopy
.width
; height
= toCopy
.height
;
781 float x
, y
, width
, height
;
784 typedef PRUptrdiff PtrBits
;
785 enum { BLOCK_SIZE_BITS
= 7, BLOCK_SIZE
= 1 << BLOCK_SIZE_BITS
}; // 128-glyph blocks
789 void Set(PRUint32 aIndex
, PRUint16 aValue
);
790 PRUint16
Get(PRUint32 aIndex
) const {
791 PRUint32 block
= aIndex
>> BLOCK_SIZE_BITS
;
792 if (block
>= mBlocks
.Length())
793 return INVALID_WIDTH
;
794 PtrBits bits
= mBlocks
[block
];
796 return INVALID_WIDTH
;
797 PRUint32 indexInBlock
= aIndex
& (BLOCK_SIZE
- 1);
799 if (GetGlyphOffset(bits
) != indexInBlock
)
800 return INVALID_WIDTH
;
801 return GetWidth(bits
);
803 PRUint16
*widths
= reinterpret_cast<PRUint16
*>(bits
);
804 return widths
[indexInBlock
];
808 PRUint32
ComputeSize();
814 static PRUint32
GetGlyphOffset(PtrBits aBits
) {
815 NS_ASSERTION(aBits
& 0x1, "This is really a pointer...");
816 return (aBits
>> 1) & ((1 << BLOCK_SIZE_BITS
) - 1);
818 static PRUint32
GetWidth(PtrBits aBits
) {
819 NS_ASSERTION(aBits
& 0x1, "This is really a pointer...");
820 return aBits
>> (1 + BLOCK_SIZE_BITS
);
822 static PtrBits
MakeSingle(PRUint32 aGlyphOffset
, PRUint16 aWidth
) {
823 return (aWidth
<< (1 + BLOCK_SIZE_BITS
)) + (aGlyphOffset
<< 1) + 1;
826 nsTArray
<PtrBits
> mBlocks
;
829 GlyphWidths mContainedGlyphWidths
;
830 nsTHashtable
<HashEntry
> mTightGlyphExtents
;
831 PRUint32 mAppUnitsPerDevUnit
;
837 * This class implements text shaping (character to glyph mapping and
838 * glyph layout). There is a gfxFontShaper subclass for each text layout
839 * technology (uniscribe, core text, harfbuzz,....) we support.
841 * The shaper is responsible for setting up glyph data in gfxTextRuns.
843 * A generic, platform-independent shaper relies only on the standard
844 * gfxFont interface and can work with any concrete subclass of gfxFont.
846 * Platform-specific implementations designed to interface to platform
847 * shaping APIs such as Uniscribe or CoreText may rely on features of a
848 * specific font subclass to access native font references
849 * (such as CTFont, HFONT, DWriteFont, etc).
852 class gfxFontShaper
{
854 gfxFontShaper(gfxFont
*aFont
)
857 NS_ASSERTION(aFont
, "shaper requires a valid font!");
860 virtual ~gfxFontShaper() { }
862 virtual PRBool
InitTextRun(gfxContext
*aContext
,
863 gfxTextRun
*aTextRun
,
864 const PRUnichar
*aString
,
867 PRInt32 aRunScript
) = 0;
869 gfxFont
*GetFont() const { return mFont
; }
872 // the font this shaper is working with
876 /* a SPECIFIC single font family */
877 class THEBES_API gfxFont
{
879 nsrefcnt
AddRef(void) {
880 NS_PRECONDITION(PRInt32(mRefCnt
) >= 0, "illegal refcnt");
881 if (mExpirationState
.IsTracked()) {
882 gfxFontCache::GetCache()->RemoveObject(this);
885 NS_LOG_ADDREF(this, mRefCnt
, "gfxFont", sizeof(*this));
888 nsrefcnt
Release(void) {
889 NS_PRECONDITION(0 != mRefCnt
, "dup release");
891 NS_LOG_RELEASE(this, mRefCnt
, "gfxFont");
894 // |this| may have been deleted.
900 PRInt32
GetRefCount() { return mRefCnt
; }
902 // options to specify the kind of AA to be used when creating a font
911 nsAutoRefCnt mRefCnt
;
913 void NotifyReleased() {
914 gfxFontCache
*cache
= gfxFontCache::GetCache();
916 // Don't delete just yet; return the object to the cache for
917 // possibly recycling within some time limit
918 cache
->NotifyReleased(this);
920 // The cache may have already been shut down.
925 gfxFont(gfxFontEntry
*aFontEntry
, const gfxFontStyle
*aFontStyle
,
926 AntialiasOption anAAOption
= kAntialiasDefault
);
931 PRBool
Valid() const {
935 // options for the kind of bounding box to return from measurement
938 // A box that encloses all the painted pixels, and may
939 // include sidebearings and/or additional ascent/descent
940 // within the glyph cell even if the ink is smaller.
942 // A box that tightly encloses all the painted pixels
943 // (although actually on Windows, at least, it may be
944 // slightly larger than strictly necessary because
945 // we can't get precise extents with ClearType).
946 TIGHT_HINTED_OUTLINE_EXTENTS
947 // A box that tightly encloses the glyph outline,
948 // ignoring possible antialiasing pixels that extend
950 // NOTE: The default implementation of gfxFont::Measure(),
951 // which works with the glyph extents cache, does not
952 // differentiate between this and TIGHT_INK_EXTENTS.
953 // Whether the distinction is important depends on the
954 // antialiasing behavior of the platform; currently the
955 // distinction is only implemented in the gfxWindowsFont
956 // subclass, because of ClearType's tendency to paint
957 // outside the hinted outline.
958 // Also NOTE: it is relatively expensive to request this,
959 // as it does not use cached glyph extents in the font.
962 const nsString
& GetName() const { return mFontEntry
->Name(); }
963 const gfxFontStyle
*GetStyle() const { return &mStyle
; }
965 virtual nsString
GetUniqueName() { return GetName(); }
967 virtual gfxFont
* CopyWithAntialiasOption(AntialiasOption anAAOption
) {
968 // platforms where this actually matters should override
972 virtual gfxFloat
GetAdjustedSize() {
973 return mAdjustedSize
> 0.0 ? mAdjustedSize
: mStyle
.size
;
976 float FUnitsToDevUnitsFactor() const {
977 // check this was set up during font initialization
978 NS_ASSERTION(mFUnitsConvFactor
> 0.0f
, "mFUnitsConvFactor not valid");
979 return mFUnitsConvFactor
;
982 // check whether this is an sfnt we can potentially use with harfbuzz
983 PRBool
FontCanSupportHarfBuzz() {
984 return mFontEntry
->HasCmapTable();
987 // Access to raw font table data (needed for Harfbuzz):
988 // returns a pointer to data owned by the fontEntry or the OS,
989 // which will remain valid until released.
991 // Default implementations forward to the font entry,
992 // and maintain a shared table.
994 // Subclasses should override this if they can provide more efficient
995 // access than getting tables with mFontEntry->GetFontTable() and sharing
996 // them via the entry.
998 // Get pointer to a specific font table, or NULL if
999 // the table doesn't exist in the font
1000 virtual hb_blob_t
*GetFontTable(PRUint32 aTag
);
1002 // Subclasses may choose to look up glyph ids for characters.
1003 // If they do not override this, gfxHarfBuzzShaper will fetch the cmap
1004 // table and use that.
1005 virtual PRBool
ProvidesGetGlyph() const {
1008 // Map unicode character to glyph ID.
1009 // Only used if ProvidesGetGlyph() returns PR_TRUE.
1010 virtual PRUint32
GetGlyph(PRUint32 unicode
, PRUint32 variation_selector
) {
1014 // subclasses may provide (possibly hinted) glyph widths (in font units);
1015 // if they do not override this, harfbuzz will use unhinted widths
1016 // derived from the font tables
1017 virtual PRBool
ProvidesGlyphWidths() {
1021 // The return value is interpreted as a horizontal advance in 16.16 fixed
1023 virtual PRInt32
GetGlyphWidth(gfxContext
*aCtx
, PRUint16 aGID
) {
1030 gfxFloat superscriptOffset
;
1031 gfxFloat subscriptOffset
;
1032 gfxFloat strikeoutSize
;
1033 gfxFloat strikeoutOffset
;
1034 gfxFloat underlineSize
;
1035 gfxFloat underlineOffset
;
1037 gfxFloat internalLeading
;
1038 gfxFloat externalLeading
;
1045 gfxFloat maxDescent
;
1046 gfxFloat maxAdvance
;
1048 gfxFloat aveCharWidth
;
1049 gfxFloat spaceWidth
;
1050 gfxFloat zeroOrAveCharWidth
; // width of '0', or if there is
1051 // no '0' glyph in this font,
1052 // equal to .aveCharWidth
1054 virtual const gfxFont::Metrics
& GetMetrics() = 0;
1057 * We let layout specify spacing on either side of any
1058 * character. We need to specify both before and after
1059 * spacing so that substring measurement can do the right things.
1060 * These values are in appunits. They're always an integral number of
1061 * appunits, but we specify them in floats in case very large spacing
1062 * values are required.
1069 * Metrics for a particular string
1071 struct THEBES_API RunMetrics
{
1073 mAdvanceWidth
= mAscent
= mDescent
= 0.0;
1074 mBoundingBox
= gfxRect(0,0,0,0);
1077 void CombineWith(const RunMetrics
& aOther
, PRBool aOtherIsOnLeft
);
1079 // can be negative (partly due to negative spacing).
1080 // Advance widths should be additive: the advance width of the
1081 // (offset1, length1) plus the advance width of (offset1 + length1,
1082 // length2) should be the advance width of (offset1, length1 + length2)
1083 gfxFloat mAdvanceWidth
;
1085 // For zero-width substrings, these must be zero!
1086 gfxFloat mAscent
; // always non-negative
1087 gfxFloat mDescent
; // always non-negative
1089 // Bounding box that is guaranteed to include everything drawn.
1090 // If a tight boundingBox was requested when these metrics were
1091 // generated, this will tightly wrap the glyphs, otherwise it is
1092 // "loose" and may be larger than the true bounding box.
1093 // Coordinates are relative to the baseline left origin, so typically
1094 // mBoundingBox.y == -mAscent
1095 gfxRect mBoundingBox
;
1099 * Draw a series of glyphs to aContext. The direction of aTextRun must
1101 * @param aStart the first character to draw
1102 * @param aEnd draw characters up to here
1103 * @param aBaselineOrigin the baseline origin; the left end of the baseline
1104 * for LTR textruns, the right end of the baseline for RTL textruns. On return,
1105 * this should be updated to the other end of the baseline. In application
1107 * @param aSpacing spacing to insert before and after characters (for RTL
1108 * glyphs, before-spacing is inserted to the right of characters). There
1109 * are aEnd - aStart elements in this array, unless it's null to indicate
1110 * that there is no spacing.
1111 * @param aDrawToPath when true, add the glyph outlines to the current path
1112 * instead of drawing the glyphs
1114 * Callers guarantee:
1115 * -- aStart and aEnd are aligned to cluster and ligature boundaries
1116 * -- all glyphs use this font
1118 * The default implementation builds a cairo glyph array and
1119 * calls cairo_show_glyphs or cairo_glyph_path.
1121 virtual void Draw(gfxTextRun
*aTextRun
, PRUint32 aStart
, PRUint32 aEnd
,
1122 gfxContext
*aContext
, PRBool aDrawToPath
, gfxPoint
*aBaselineOrigin
,
1125 * Measure a run of characters. See gfxTextRun::Metrics.
1126 * @param aTight if false, then return the union of the glyph extents
1127 * with the font-box for the characters (the rectangle with x=0,width=
1128 * the advance width for the character run,y=-(font ascent), and height=
1129 * font ascent + font descent). Otherwise, we must return as tight as possible
1130 * an approximation to the area actually painted by glyphs.
1131 * @param aContextForTightBoundingBox when aTight is true, this must
1133 * @param aSpacing spacing to insert before and after glyphs. The bounding box
1134 * need not include the spacing itself, but the spacing affects the glyph
1135 * positions. null if there is no spacing.
1137 * Callers guarantee:
1138 * -- aStart and aEnd are aligned to cluster and ligature boundaries
1139 * -- all glyphs use this font
1141 * The default implementation just uses font metrics and aTextRun's
1142 * advances, and assumes no characters fall outside the font box. In
1143 * general this is insufficient, because that assumption is not always true.
1145 virtual RunMetrics
Measure(gfxTextRun
*aTextRun
,
1146 PRUint32 aStart
, PRUint32 aEnd
,
1147 BoundingBoxType aBoundingBoxType
,
1148 gfxContext
*aContextForTightBoundingBox
,
1151 * Line breaks have been changed at the beginning and/or end of a substring
1152 * of the text. Reshaping may be required; glyph updating is permitted.
1153 * @return true if anything was changed, false otherwise
1155 PRBool
NotifyLineBreaksChanged(gfxTextRun
*aTextRun
,
1156 PRUint32 aStart
, PRUint32 aLength
)
1157 { return PR_FALSE
; }
1159 // Expiration tracking
1160 nsExpirationState
*GetExpirationState() { return &mExpirationState
; }
1162 // Get the glyphID of a space
1163 virtual PRUint32
GetSpaceGlyph() = 0;
1165 gfxGlyphExtents
*GetOrCreateGlyphExtents(PRUint32 aAppUnitsPerDevUnit
);
1167 // You need to call SetupCairoFont on the aCR just before calling this
1168 virtual void SetupGlyphExtents(gfxContext
*aContext
, PRUint32 aGlyphID
,
1169 PRBool aNeedTight
, gfxGlyphExtents
*aExtents
);
1171 // This is called by the default Draw() implementation above.
1172 virtual PRBool
SetupCairoFont(gfxContext
*aContext
) = 0;
1174 PRBool
IsSyntheticBold() { return mSyntheticBoldOffset
!= 0; }
1175 PRUint32
GetSyntheticBoldOffset() { return mSyntheticBoldOffset
; }
1177 gfxFontEntry
*GetFontEntry() { return mFontEntry
.get(); }
1178 PRBool
HasCharacter(PRUint32 ch
) {
1181 return mFontEntry
->HasCharacter(ch
);
1184 PRUint16
GetUVSGlyph(PRUint32 aCh
, PRUint32 aVS
) {
1188 return mFontEntry
->GetUVSGlyph(aCh
, aVS
);
1191 // call the (virtual) InitTextRun method to do glyph generation/shaping,
1192 // limiting the length of text passed by processing the run in multiple
1193 // segments if necessary
1194 PRBool
SplitAndInitTextRun(gfxContext
*aContext
,
1195 gfxTextRun
*aTextRun
,
1196 const PRUnichar
*aString
,
1198 PRUint32 aRunLength
,
1199 PRInt32 aRunScript
);
1202 nsRefPtr
<gfxFontEntry
> mFontEntry
;
1204 PRPackedBool mIsValid
;
1205 nsExpirationState mExpirationState
;
1206 gfxFontStyle mStyle
;
1207 nsAutoTArray
<gfxGlyphExtents
*,1> mGlyphExtentsArray
;
1209 gfxFloat mAdjustedSize
;
1211 float mFUnitsConvFactor
; // conversion factor from font units to dev units
1213 // synthetic bolding for environments where this is not supported by the platform
1214 PRUint32 mSyntheticBoldOffset
; // number of devunit pixels to offset double-strike, 0 ==> no bolding
1216 // the AA setting requested for this font - may affect glyph bounds
1217 AntialiasOption mAntialiasOption
;
1219 // a copy of the font without antialiasing, if needed for separate
1220 // measurement by mathml code
1221 nsAutoPtr
<gfxFont
> mNonAAFont
;
1223 // we may switch between these shapers on the fly, based on the script
1224 // of the text run being shaped
1225 nsAutoPtr
<gfxFontShaper
> mPlatformShaper
;
1226 nsAutoPtr
<gfxFontShaper
> mHarfBuzzShaper
;
1228 // Create a default platform text shaper for this font.
1229 // (TODO: This should become pure virtual once all font backends have
1231 virtual void CreatePlatformShaper() { }
1233 // Helper for subclasses that want to initialize standard metrics from the
1234 // tables of sfnt (TrueType/OpenType) fonts.
1235 // This will use mFUnitsConvFactor if it is already set, else compute it
1236 // from mAdjustedSize and the unitsPerEm in the font's 'head' table.
1237 // Returns TRUE and sets mIsValid=TRUE if successful;
1238 // Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
1239 // Returns FALSE if the font does not appear to be an sfnt at all,
1240 // and should be handled (if possible) using other APIs.
1241 PRBool
InitMetricsFromSfntTables(Metrics
& aMetrics
);
1243 // Helper to calculate various derived metrics from the results of
1244 // InitMetricsFromSfntTables or equivalent platform code
1245 void CalculateDerivedMetrics(Metrics
& aMetrics
);
1247 // some fonts have bad metrics, this method sanitize them.
1248 // if this font has bad underline offset, aIsBadUnderlineFont should be true.
1249 void SanitizeMetrics(gfxFont::Metrics
*aMetrics
, PRBool aIsBadUnderlineFont
);
1251 // Default simply calls m[Platform|HarfBuzz]Shaper->InitTextRun().
1252 // Override if the font class wants to give special handling
1253 // to shaper failure.
1254 // Returns PR_FALSE if shaping failed (though currently we
1255 // don't have any good way to handle that situation).
1256 virtual PRBool
InitTextRun(gfxContext
*aContext
,
1257 gfxTextRun
*aTextRun
,
1258 const PRUnichar
*aString
,
1260 PRUint32 aRunLength
,
1262 PRBool aPreferPlatformShaping
= PR_FALSE
);
1265 // proportion of ascent used for x-height, if unable to read value from font
1266 #define DEFAULT_XHEIGHT_FACTOR 0.56f
1268 class THEBES_API gfxTextRunFactory
{
1269 NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory
)
1272 // Flags in the mask 0xFFFF0000 are reserved for textrun clients
1273 // Flags in the mask 0x0000F000 are reserved for per-platform fonts
1274 // Flags in the mask 0x00000FFF are set by the textrun creator.
1276 CACHE_TEXT_FLAGS
= 0xF0000000,
1277 USER_TEXT_FLAGS
= 0x0FFF0000,
1278 PLATFORM_TEXT_FLAGS
= 0x0000F000,
1279 TEXTRUN_TEXT_FLAGS
= 0x00000FFF,
1280 SETTABLE_FLAGS
= CACHE_TEXT_FLAGS
| USER_TEXT_FLAGS
,
1283 * When set, the text string pointer used to create the text run
1284 * is guaranteed to be available during the lifetime of the text run.
1286 TEXT_IS_PERSISTENT
= 0x0001,
1288 * When set, the text is known to be all-ASCII (< 128).
1290 TEXT_IS_ASCII
= 0x0002,
1292 * When set, the text is RTL.
1294 TEXT_IS_RTL
= 0x0004,
1296 * When set, spacing is enabled and the textrun needs to call GetSpacing
1297 * on the spacing provider.
1299 TEXT_ENABLE_SPACING
= 0x0008,
1301 * When set, GetHyphenationBreaks may return true for some character
1302 * positions, otherwise it will always return false for all characters.
1304 TEXT_ENABLE_HYPHEN_BREAKS
= 0x0010,
1306 * When set, the text has no characters above 255 and it is stored
1307 * in the textrun in 8-bit format.
1309 TEXT_IS_8BIT
= 0x0020,
1311 * When set, the RunMetrics::mBoundingBox field will be initialized
1312 * properly based on glyph extents, in particular, glyph extents that
1313 * overflow the standard font-box (the box defined by the ascent, descent
1314 * and advance width of the glyph). When not set, it may just be the
1315 * standard font-box even if glyphs overflow.
1317 TEXT_NEED_BOUNDING_BOX
= 0x0040,
1319 * When set, optional ligatures are disabled. Ligatures that are
1320 * required for legible text should still be enabled.
1322 TEXT_DISABLE_OPTIONAL_LIGATURES
= 0x0080,
1324 * When set, the textrun should favour speed of construction over
1325 * quality. This may involve disabling ligatures and/or kerning or
1328 TEXT_OPTIMIZE_SPEED
= 0x0100
1332 * This record contains all the parameters needed to initialize a textrun.
1335 // A reference context suggesting where the textrun will be rendered
1336 gfxContext
*mContext
;
1337 // Pointer to arbitrary user data (which should outlive the textrun)
1339 // A description of which characters have been stripped from the original
1340 // DOM string to produce the characters in the textrun. May be null
1341 // if that information is not relevant.
1342 gfxSkipChars
*mSkipChars
;
1343 // A list of where linebreaks are currently placed in the textrun. May
1344 // be null if mInitialBreakCount is zero.
1345 PRUint32
*mInitialBreaks
;
1346 PRUint32 mInitialBreakCount
;
1347 // The ratio to use to convert device pixels to application layout units
1348 PRUint32 mAppUnitsPerDevUnit
;
1351 virtual ~gfxTextRunFactory() {}
1355 * gfxTextRun is an abstraction for drawing and measuring substrings of a run
1356 * of text. It stores runs of positioned glyph data, each run having a single
1357 * gfxFont. The glyphs are associated with a string of source text, and the
1358 * gfxTextRun APIs take parameters that are offsets into that source text.
1360 * gfxTextRuns are not refcounted. They should be deleted when no longer required.
1362 * gfxTextRuns are mostly immutable. The only things that can change are
1363 * inter-cluster spacing and line break placement. Spacing is always obtained
1364 * lazily by methods that need it, it is not cached. Line breaks are stored
1365 * persistently (insofar as they affect the shaping of glyphs; gfxTextRun does
1366 * not actually do anything to explicitly account for line breaks). Initially
1367 * there are no line breaks. The textrun can record line breaks before or after
1368 * any given cluster. (Line breaks specified inside clusters are ignored.)
1370 * It is important that zero-length substrings are handled correctly. This will
1373 * gfxTextRun stores a list of zero or more glyphs for each character. For each
1374 * glyph we store the glyph ID, the advance, and possibly an xoffset and yoffset.
1375 * The idea is that a string is rendered by a loop that draws each glyph
1376 * at its designated offset from the current point, then advances the current
1377 * point by the glyph's advance in the direction of the textrun (LTR or RTL).
1378 * Each glyph advance is always rounded to the nearest appunit; this ensures
1379 * consistent results when dividing the text in a textrun into multiple text
1380 * frames (frame boundaries are always aligned to appunits). We optimize
1381 * for the case where a character has a single glyph and zero xoffset and yoffset,
1382 * and the glyph ID and advance are in a reasonable range so we can pack all
1383 * necessary data into 32 bits.
1385 * gfxTextRun methods that measure or draw substrings will associate all the
1386 * glyphs in a cluster with the first character of the cluster; if that character
1387 * is in the substring, the glyphs will be measured or drawn, otherwise they
1390 class THEBES_API gfxTextRun
{
1392 virtual ~gfxTextRun();
1394 typedef gfxFont::RunMetrics Metrics
;
1396 // Public textrun API for general use
1398 PRBool
IsClusterStart(PRUint32 aPos
) {
1399 NS_ASSERTION(0 <= aPos
&& aPos
< mCharacterCount
, "aPos out of range");
1400 return mCharacterGlyphs
[aPos
].IsClusterStart();
1402 PRBool
IsLigatureGroupStart(PRUint32 aPos
) {
1403 NS_ASSERTION(0 <= aPos
&& aPos
< mCharacterCount
, "aPos out of range");
1404 return mCharacterGlyphs
[aPos
].IsLigatureGroupStart();
1406 PRBool
CanBreakLineBefore(PRUint32 aPos
) {
1407 NS_ASSERTION(0 <= aPos
&& aPos
< mCharacterCount
, "aPos out of range");
1408 return mCharacterGlyphs
[aPos
].CanBreakBefore();
1411 PRUint32
GetLength() { return mCharacterCount
; }
1413 // All PRUint32 aStart, PRUint32 aLength ranges below are restricted to
1414 // grapheme cluster boundaries! All offsets are in terms of the string
1415 // passed into MakeTextRun.
1417 // All coordinates are in layout/app units
1420 * Set the potential linebreaks for a substring of the textrun. These are
1421 * the "allow break before" points. Initially, there are no potential
1424 * This can change glyphs and/or geometry! Some textruns' shapes
1425 * depend on potential line breaks (e.g., title-case-converting textruns).
1426 * This function is virtual so that those textruns can reshape themselves.
1428 * @return true if this changed the linebreaks, false if the new line
1429 * breaks are the same as the old
1431 virtual PRBool
SetPotentialLineBreaks(PRUint32 aStart
, PRUint32 aLength
,
1432 PRPackedBool
*aBreakBefore
,
1433 gfxContext
*aRefContext
);
1436 * Layout provides PropertyProvider objects. These allow detection of
1437 * potential line break points and computation of spacing. We pass the data
1438 * this way to allow lazy data acquisition; for example BreakAndMeasureText
1439 * will want to only ask for properties of text it's actually looking at.
1441 * NOTE that requested spacing may not actually be applied, if the textrun
1442 * is unable to apply it in some context. Exception: spacing around a
1443 * whitespace character MUST always be applied.
1445 class PropertyProvider
{
1447 // Detect hyphenation break opportunities in the given range; breaks
1448 // not at cluster boundaries will be ignored.
1449 virtual void GetHyphenationBreaks(PRUint32 aStart
, PRUint32 aLength
,
1450 PRPackedBool
*aBreakBefore
) = 0;
1452 // Returns the extra width that will be consumed by a hyphen. This should
1453 // be constant for a given textrun.
1454 virtual gfxFloat
GetHyphenWidth() = 0;
1456 typedef gfxFont::Spacing Spacing
;
1459 * Get the spacing around the indicated characters. Spacing must be zero
1460 * inside clusters. In other words, if character i is not
1461 * CLUSTER_START, then character i-1 must have zero after-spacing and
1462 * character i must have zero before-spacing.
1464 virtual void GetSpacing(PRUint32 aStart
, PRUint32 aLength
,
1465 Spacing
*aSpacing
) = 0;
1469 * Draws a substring. Uses only GetSpacing from aBreakProvider.
1470 * The provided point is the baseline origin on the left of the string
1471 * for LTR, on the right of the string for RTL.
1472 * @param aAdvanceWidth if non-null, the advance width of the substring
1475 * Drawing should respect advance widths in the sense that for LTR runs,
1476 * Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by
1477 * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1 + length1, length2,
1478 * dirty, &provider, nsnull) should have the same effect as
1479 * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
1480 * For RTL runs the rule is:
1481 * Draw(ctx, pt, offset1 + length1, length2, dirty, &provider, &advance) followed by
1482 * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1, length1,
1483 * dirty, &provider, nsnull) should have the same effect as
1484 * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
1486 * Glyphs should be drawn in logical content order, which can be significant
1487 * if they overlap (perhaps due to negative spacing).
1489 void Draw(gfxContext
*aContext
, gfxPoint aPt
,
1490 PRUint32 aStart
, PRUint32 aLength
,
1491 PropertyProvider
*aProvider
,
1492 gfxFloat
*aAdvanceWidth
);
1495 * Renders a substring to a path. Uses only GetSpacing from aBreakProvider.
1496 * The provided point is the baseline origin on the left of the string
1497 * for LTR, on the right of the string for RTL.
1498 * @param aAdvanceWidth if non-null, the advance width of the substring
1501 * Drawing should respect advance widths in the way that Draw above does.
1503 * Glyphs should be drawn in logical content order.
1505 * UNLIKE Draw above, this cannot be used to render substrings that start or
1506 * end inside a ligature.
1508 void DrawToPath(gfxContext
*aContext
, gfxPoint aPt
,
1509 PRUint32 aStart
, PRUint32 aLength
,
1510 PropertyProvider
*aBreakProvider
,
1511 gfxFloat
*aAdvanceWidth
);
1514 * Computes the ReflowMetrics for a substring.
1515 * Uses GetSpacing from aBreakProvider.
1516 * @param aBoundingBoxType which kind of bounding box (loose/tight)
1518 Metrics
MeasureText(PRUint32 aStart
, PRUint32 aLength
,
1519 gfxFont::BoundingBoxType aBoundingBoxType
,
1520 gfxContext
*aRefContextForTightBoundingBox
,
1521 PropertyProvider
*aProvider
);
1524 * Computes just the advance width for a substring.
1525 * Uses GetSpacing from aBreakProvider.
1527 gfxFloat
GetAdvanceWidth(PRUint32 aStart
, PRUint32 aLength
,
1528 PropertyProvider
*aProvider
);
1531 * Clear all stored line breaks for the given range (both before and after),
1532 * and then set the line-break state before aStart to aBreakBefore and
1533 * after the last cluster to aBreakAfter.
1535 * We require that before and after line breaks be consistent. For clusters
1536 * i and i+1, we require that if there is a break after cluster i, a break
1537 * will be specified before cluster i+1. This may be temporarily violated
1538 * (e.g. after reflowing line L and before reflowing line L+1); to handle
1539 * these temporary violations, we say that there is a break betwen i and i+1
1540 * if a break is specified after i OR a break is specified before i+1.
1542 * This can change textrun geometry! The existence of a linebreak can affect
1543 * the advance width of the cluster before the break (when kerning) or the
1544 * geometry of one cluster before the break or any number of clusters
1545 * after the break. (The one-cluster-before-the-break limit is somewhat
1546 * arbitrary; if some scripts require breaking it, then we need to
1547 * alter nsTextFrame::TrimTrailingWhitespace, perhaps drastically becase
1548 * it could affect the layout of frames before it...)
1550 * We return true if glyphs or geometry changed, false otherwise. This
1551 * function is virtual so that gfxTextRun subclasses can reshape
1554 * @param aAdvanceWidthDelta if non-null, returns the change in advance
1555 * width of the given range.
1557 virtual PRBool
SetLineBreaks(PRUint32 aStart
, PRUint32 aLength
,
1558 PRBool aLineBreakBefore
, PRBool aLineBreakAfter
,
1559 gfxFloat
*aAdvanceWidthDelta
,
1560 gfxContext
*aRefContext
);
1563 * Finds the longest substring that will fit into the given width.
1564 * Uses GetHyphenationBreaks and GetSpacing from aBreakProvider.
1565 * Guarantees the following:
1566 * -- 0 <= result <= aMaxLength
1567 * -- result is the maximal value of N such that either
1568 * N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
1569 * OR N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
1570 * OR N == aMaxLength && GetAdvanceWidth(aStart, N) <= aWidth
1571 * where GetAdvanceWidth assumes the effect of
1572 * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
1573 * -- if no such N exists, then result is the smallest N such that
1574 * N < aMaxLength && line break at N
1575 * OR N < aMaxLength && hyphen break at N
1576 * OR N == aMaxLength
1578 * The call has the effect of
1579 * SetLineBreaks(aStart, result, aLineBreakBefore, result < aMaxLength, aProvider)
1580 * and the returned metrics and the invariants above reflect this.
1582 * @param aMaxLength this can be PR_UINT32_MAX, in which case the length used
1583 * is up to the end of the string
1584 * @param aLineBreakBefore set to true if and only if there is an actual
1585 * line break at the start of this string.
1586 * @param aSuppressInitialBreak if true, then we assume there is no possible
1587 * linebreak before aStart. If false, then we will check the internal
1588 * line break opportunity state before deciding whether to return 0 as the
1589 * character to break before.
1590 * @param aTrimWhitespace if non-null, then we allow a trailing run of
1591 * spaces to be trimmed; the width of the space(s) will not be included in
1592 * the measured string width for comparison with the limit aWidth, and
1593 * trimmed spaces will not be included in returned metrics. The width
1594 * of the trimmed spaces will be returned in aTrimWhitespace.
1595 * Trimmed spaces are still counted in the "characters fit" result.
1596 * @param aMetrics if non-null, we fill this in for the returned substring.
1597 * If a hyphenation break was used, the hyphen is NOT included in the returned metrics.
1598 * @param aBoundingBoxType whether to make the bounding box in aMetrics tight
1599 * @param aRefContextForTightBoundingBox a reference context to get the
1600 * tight bounding box, if requested
1601 * @param aUsedHyphenation if non-null, records if we selected a hyphenation break
1602 * @param aLastBreak if non-null and result is aMaxLength, we set this to
1603 * the maximal N such that
1604 * N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
1605 * OR N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
1606 * or PR_UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
1608 * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
1610 * @param aCanWordWrap true if we can break between any two grapheme
1611 * clusters. This is set by word-wrap: break-word
1613 * @param aBreakPriority in/out the priority of the break opportunity
1614 * saved in the line. If we are prioritizing break opportunities, we will
1615 * not set a break with a lower priority. @see gfxBreakPriority.
1617 * Note that negative advance widths are possible especially if negative
1618 * spacing is provided.
1620 PRUint32
BreakAndMeasureText(PRUint32 aStart
, PRUint32 aMaxLength
,
1621 PRBool aLineBreakBefore
, gfxFloat aWidth
,
1622 PropertyProvider
*aProvider
,
1623 PRBool aSuppressInitialBreak
,
1624 gfxFloat
*aTrimWhitespace
,
1626 gfxFont::BoundingBoxType aBoundingBoxType
,
1627 gfxContext
*aRefContextForTightBoundingBox
,
1628 PRBool
*aUsedHyphenation
,
1629 PRUint32
*aLastBreak
,
1630 PRBool aCanWordWrap
,
1631 gfxBreakPriority
*aBreakPriority
);
1634 * Update the reference context.
1635 * XXX this is a hack. New text frame does not call this. Use only
1636 * temporarily for old text frame.
1638 void SetContext(gfxContext
*aContext
) {}
1642 PRBool
IsRightToLeft() const { return (mFlags
& gfxTextRunFactory::TEXT_IS_RTL
) != 0; }
1643 gfxFloat
GetDirection() const { return (mFlags
& gfxTextRunFactory::TEXT_IS_RTL
) ? -1.0 : 1.0; }
1644 void *GetUserData() const { return mUserData
; }
1645 void SetUserData(void *aUserData
) { mUserData
= aUserData
; }
1646 PRUint32
GetFlags() const { return mFlags
; }
1647 void SetFlagBits(PRUint32 aFlags
) {
1648 NS_ASSERTION(!(aFlags
& ~gfxTextRunFactory::SETTABLE_FLAGS
),
1649 "Only user flags should be mutable");
1652 void ClearFlagBits(PRUint32 aFlags
) {
1653 NS_ASSERTION(!(aFlags
& ~gfxTextRunFactory::SETTABLE_FLAGS
),
1654 "Only user flags should be mutable");
1657 const gfxSkipChars
& GetSkipChars() const { return mSkipChars
; }
1658 PRUint32
GetAppUnitsPerDevUnit() const { return mAppUnitsPerDevUnit
; }
1659 gfxFontGroup
*GetFontGroup() const { return mFontGroup
; }
1660 const PRUint8
*GetText8Bit() const
1661 { return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
) ? mText
.mSingle
: nsnull
; }
1662 const PRUnichar
*GetTextUnicode() const
1663 { return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
) ? nsnull
: mText
.mDouble
; }
1664 const void *GetTextAt(PRUint32 aIndex
) {
1665 return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
)
1666 ? static_cast<const void *>(mText
.mSingle
+ aIndex
)
1667 : static_cast<const void *>(mText
.mDouble
+ aIndex
);
1669 const PRUnichar
GetChar(PRUint32 i
) const
1670 { return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
) ? mText
.mSingle
[i
] : mText
.mDouble
[i
]; }
1671 PRUint32
GetHashCode() const { return mHashCode
; }
1672 void SetHashCode(PRUint32 aHash
) { mHashCode
= aHash
; }
1674 // Call this, don't call "new gfxTextRun" directly. This does custom
1675 // allocation and initialization
1676 static gfxTextRun
*Create(const gfxTextRunFactory::Parameters
*aParams
,
1677 const void *aText
, PRUint32 aLength
, gfxFontGroup
*aFontGroup
, PRUint32 aFlags
);
1679 // Clone this textrun, according to the given parameters. This textrun's
1680 // glyph data is copied, so the text and length must be the same as this
1681 // textrun's. If there's a problem, return null. Actual linebreaks will
1682 // be set as per aParams; there will be no potential linebreaks.
1683 // If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
1684 // textrun will copy it.
1685 virtual gfxTextRun
*Clone(const gfxTextRunFactory::Parameters
*aParams
, const void *aText
,
1686 PRUint32 aLength
, gfxFontGroup
*aFontGroup
, PRUint32 aFlags
);
1689 * This class records the information associated with a character in the
1690 * input string. It's optimized for the case where there is one glyph
1691 * representing that character alone.
1693 * A character can have zero or more associated glyphs. Each glyph
1694 * has an advance width and an x and y offset.
1695 * A character may be the start of a cluster.
1696 * A character may be the start of a ligature group.
1697 * A character can be "missing", indicating that the system is unable
1698 * to render the character.
1700 * All characters in a ligature group conceptually share all the glyphs
1701 * associated with the characters in a group.
1703 class CompressedGlyph
{
1705 CompressedGlyph() { mValue
= 0; }
1708 // Indicates that a cluster and ligature group starts at this
1709 // character; this character has a single glyph with a reasonable
1710 // advance and zero offsets. A "reasonable" advance
1711 // is one that fits in the available bits (currently 14) (specified
1713 FLAG_IS_SIMPLE_GLYPH
= 0x80000000U
,
1714 // Indicates that a linebreak is allowed before this character
1715 FLAG_CAN_BREAK_BEFORE
= 0x40000000U
,
1717 // The advance is stored in appunits
1718 ADVANCE_MASK
= 0x3FFF0000U
,
1721 GLYPH_MASK
= 0x0000FFFFU
,
1723 // Non-simple glyphs may or may not have glyph data in the
1724 // corresponding mDetailedGlyphs entry. They have the following
1727 // When NOT set, indicates that this character corresponds to a
1728 // missing glyph and should be skipped (or possibly, render the character
1729 // Unicode value in some special way). If there are glyphs,
1730 // the mGlyphID is actually the UTF16 character code. The bit is
1731 // inverted so we can memset the array to zero to indicate all missing.
1732 FLAG_NOT_MISSING
= 0x01,
1733 FLAG_NOT_CLUSTER_START
= 0x02,
1734 FLAG_NOT_LIGATURE_GROUP_START
= 0x04,
1736 GLYPH_COUNT_MASK
= 0x00FFFF00U
,
1737 GLYPH_COUNT_SHIFT
= 8
1740 // "Simple glyphs" have a simple glyph ID, simple advance and their
1741 // x and y offsets are zero. Also the glyph extents do not overflow
1742 // the font-box defined by the font ascent, descent and glyph advance width.
1743 // These case is optimized to avoid storing DetailedGlyphs.
1745 // Returns true if the glyph ID aGlyph fits into the compressed representation
1746 static PRBool
IsSimpleGlyphID(PRUint32 aGlyph
) {
1747 return (aGlyph
& GLYPH_MASK
) == aGlyph
;
1749 // Returns true if the advance aAdvance fits into the compressed representation.
1750 // aAdvance is in appunits.
1751 static PRBool
IsSimpleAdvance(PRUint32 aAdvance
) {
1752 return (aAdvance
& (ADVANCE_MASK
>> ADVANCE_SHIFT
)) == aAdvance
;
1755 PRBool
IsSimpleGlyph() const { return (mValue
& FLAG_IS_SIMPLE_GLYPH
) != 0; }
1756 PRUint32
GetSimpleAdvance() const { return (mValue
& ADVANCE_MASK
) >> ADVANCE_SHIFT
; }
1757 PRUint32
GetSimpleGlyph() const { return mValue
& GLYPH_MASK
; }
1759 PRBool
IsMissing() const { return (mValue
& (FLAG_NOT_MISSING
|FLAG_IS_SIMPLE_GLYPH
)) == 0; }
1760 PRBool
IsClusterStart() const {
1761 return (mValue
& FLAG_IS_SIMPLE_GLYPH
) || !(mValue
& FLAG_NOT_CLUSTER_START
);
1763 PRBool
IsLigatureGroupStart() const {
1764 return (mValue
& FLAG_IS_SIMPLE_GLYPH
) || !(mValue
& FLAG_NOT_LIGATURE_GROUP_START
);
1766 PRBool
IsLigatureContinuation() const {
1767 return (mValue
& FLAG_IS_SIMPLE_GLYPH
) == 0 &&
1768 (mValue
& (FLAG_NOT_LIGATURE_GROUP_START
| FLAG_NOT_MISSING
)) ==
1769 (FLAG_NOT_LIGATURE_GROUP_START
| FLAG_NOT_MISSING
);
1772 PRBool
CanBreakBefore() const { return (mValue
& FLAG_CAN_BREAK_BEFORE
) != 0; }
1773 // Returns FLAG_CAN_BREAK_BEFORE if the setting changed, 0 otherwise
1774 PRUint32
SetCanBreakBefore(PRBool aCanBreakBefore
) {
1775 NS_ASSERTION(aCanBreakBefore
== PR_FALSE
|| aCanBreakBefore
== PR_TRUE
,
1776 "Bogus break-before value!");
1777 PRUint32 breakMask
= aCanBreakBefore
*FLAG_CAN_BREAK_BEFORE
;
1778 PRUint32 toggle
= breakMask
^ (mValue
& FLAG_CAN_BREAK_BEFORE
);
1783 CompressedGlyph
& SetSimpleGlyph(PRUint32 aAdvanceAppUnits
, PRUint32 aGlyph
) {
1784 NS_ASSERTION(IsSimpleAdvance(aAdvanceAppUnits
), "Advance overflow");
1785 NS_ASSERTION(IsSimpleGlyphID(aGlyph
), "Glyph overflow");
1786 mValue
= (mValue
& FLAG_CAN_BREAK_BEFORE
) | FLAG_IS_SIMPLE_GLYPH
|
1787 (aAdvanceAppUnits
<< ADVANCE_SHIFT
) | aGlyph
;
1790 CompressedGlyph
& SetComplex(PRBool aClusterStart
, PRBool aLigatureStart
,
1791 PRUint32 aGlyphCount
) {
1792 mValue
= (mValue
& FLAG_CAN_BREAK_BEFORE
) | FLAG_NOT_MISSING
|
1793 (aClusterStart
? 0 : FLAG_NOT_CLUSTER_START
) |
1794 (aLigatureStart
? 0 : FLAG_NOT_LIGATURE_GROUP_START
) |
1795 (aGlyphCount
<< GLYPH_COUNT_SHIFT
);
1799 * Missing glyphs are treated as ligature group starts; don't mess with
1800 * the cluster-start flag (see bugs 618870 and 619286).
1802 CompressedGlyph
& SetMissing(PRUint32 aGlyphCount
) {
1803 mValue
= (mValue
& (FLAG_CAN_BREAK_BEFORE
| FLAG_NOT_CLUSTER_START
)) |
1804 (aGlyphCount
<< GLYPH_COUNT_SHIFT
);
1807 PRUint32
GetGlyphCount() const {
1808 NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
1809 return (mValue
& GLYPH_COUNT_MASK
) >> GLYPH_COUNT_SHIFT
;
1817 * When the glyphs for a character don't fit into a CompressedGlyph record
1818 * in SimpleGlyph format, we use an array of DetailedGlyphs instead.
1820 struct DetailedGlyph
{
1821 /** The glyphID, or the Unicode character
1822 * if this is a missing glyph */
1824 /** The advance, x-offset and y-offset of the glyph, in appunits
1825 * mAdvance is in the text direction (RTL or LTR)
1826 * mXOffset is always from left to right
1827 * mYOffset is always from top to bottom */
1829 float mXOffset
, mYOffset
;
1832 // The text is divided into GlyphRuns as necessary
1834 nsRefPtr
<gfxFont
> mFont
; // never null
1835 PRUint32 mCharacterOffset
; // into original UTF16 string
1838 class THEBES_API GlyphRunIterator
{
1840 GlyphRunIterator(gfxTextRun
*aTextRun
, PRUint32 aStart
, PRUint32 aLength
)
1841 : mTextRun(aTextRun
), mStartOffset(aStart
), mEndOffset(aStart
+ aLength
) {
1842 mNextIndex
= mTextRun
->FindFirstGlyphRunContaining(aStart
);
1845 GlyphRun
*GetGlyphRun() { return mGlyphRun
; }
1846 PRUint32
GetStringStart() { return mStringStart
; }
1847 PRUint32
GetStringEnd() { return mStringEnd
; }
1849 gfxTextRun
*mTextRun
;
1850 GlyphRun
*mGlyphRun
;
1851 PRUint32 mStringStart
;
1852 PRUint32 mStringEnd
;
1853 PRUint32 mNextIndex
;
1854 PRUint32 mStartOffset
;
1855 PRUint32 mEndOffset
;
1858 class GlyphRunOffsetComparator
{
1860 PRBool
Equals(const GlyphRun
& a
,
1861 const GlyphRun
& b
) const
1863 return a
.mCharacterOffset
== b
.mCharacterOffset
;
1866 PRBool
LessThan(const GlyphRun
& a
,
1867 const GlyphRun
& b
) const
1869 return a
.mCharacterOffset
< b
.mCharacterOffset
;
1873 friend class GlyphRunIterator
;
1874 friend class FontSelector
;
1876 // API for setting up the textrun glyphs. Should only be called by
1877 // things that construct textruns.
1879 * We've found a run of text that should use a particular font. Call this
1880 * only during initialization when font substitution has been computed.
1881 * Call it before setting up the glyphs for the characters in this run;
1882 * SetMissingGlyph requires that the correct glyphrun be installed.
1884 * If aForceNewRun, a new glyph run will be added, even if the
1885 * previously added run uses the same font. If glyph runs are
1886 * added out of strictly increasing aStartCharIndex order (via
1887 * force), then SortGlyphRuns must be called after all glyph runs
1888 * are added before any further operations are performed with this
1891 nsresult
AddGlyphRun(gfxFont
*aFont
, PRUint32 aStartCharIndex
, PRBool aForceNewRun
= PR_FALSE
);
1892 void ResetGlyphRuns() { mGlyphRuns
.Clear(); }
1893 void SortGlyphRuns();
1894 void SanitizeGlyphRuns();
1896 // Call the following glyph-setters during initialization or during reshaping
1897 // only. It is OK to overwrite existing data for a character.
1899 * Set the glyph data for a character. aGlyphs may be null if aGlyph is a
1900 * simple glyph or has no associated glyphs. If non-null the data is copied,
1901 * the caller retains ownership.
1903 void SetSimpleGlyph(PRUint32 aCharIndex
, CompressedGlyph aGlyph
) {
1904 NS_ASSERTION(aGlyph
.IsSimpleGlyph(), "Should be a simple glyph here");
1905 if (mCharacterGlyphs
) {
1906 mCharacterGlyphs
[aCharIndex
] = aGlyph
;
1909 void SetGlyphs(PRUint32 aCharIndex
, CompressedGlyph aGlyph
,
1910 const DetailedGlyph
*aGlyphs
);
1911 void SetMissingGlyph(PRUint32 aCharIndex
, PRUint32 aUnicodeChar
);
1912 void SetSpaceGlyph(gfxFont
*aFont
, gfxContext
*aContext
, PRUint32 aCharIndex
);
1914 // If the character at aIndex is default-ignorable, set the glyph
1915 // to be invisible-missing and return TRUE, else return FALSE
1916 PRBool
FilterIfIgnorable(PRUint32 aIndex
);
1919 * Prefetch all the glyph extents needed to ensure that Measure calls
1920 * on this textrun not requesting tight boundingBoxes will succeed. Note
1921 * that some glyph extents might not be fetched due to OOM or other
1924 void FetchGlyphExtents(gfxContext
*aRefContext
);
1926 // API for access to the raw glyph data, needed by gfxFont::Draw
1927 // and gfxFont::GetBoundingBox
1928 const CompressedGlyph
*GetCharacterGlyphs() { return mCharacterGlyphs
; }
1930 // NOTE that this must not be called for a character offset that does
1931 // not have any DetailedGlyph records; callers must have verified that
1932 // mCharacterGlyphs[aCharIndex].GetGlyphCount() is greater than zero.
1933 DetailedGlyph
*GetDetailedGlyphs(PRUint32 aCharIndex
) {
1934 NS_ASSERTION(mDetailedGlyphs
!= nsnull
&&
1935 !mCharacterGlyphs
[aCharIndex
].IsSimpleGlyph() &&
1936 mCharacterGlyphs
[aCharIndex
].GetGlyphCount() > 0,
1937 "invalid use of GetDetailedGlyphs; check the caller!");
1938 return mDetailedGlyphs
->Get(aCharIndex
);
1941 PRBool
HasDetailedGlyphs() { return mDetailedGlyphs
!= nsnull
; }
1942 PRUint32
CountMissingGlyphs();
1943 const GlyphRun
*GetGlyphRuns(PRUint32
*aNumGlyphRuns
) {
1944 *aNumGlyphRuns
= mGlyphRuns
.Length();
1945 return mGlyphRuns
.Elements();
1947 // Returns the index of the GlyphRun containing the given offset.
1948 // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
1949 PRUint32
FindFirstGlyphRunContaining(PRUint32 aOffset
);
1950 // Copy glyph data for a range of characters from aSource to this
1952 virtual void CopyGlyphDataFrom(gfxTextRun
*aSource
, PRUint32 aStart
,
1953 PRUint32 aLength
, PRUint32 aDest
);
1955 nsExpirationState
*GetExpirationState() { return &mExpirationState
; }
1957 struct LigatureData
{
1958 // textrun offsets of the start and end of the containing ligature
1959 PRUint32 mLigatureStart
;
1960 PRUint32 mLigatureEnd
;
1961 // appunits advance to the start of the ligature part within the ligature;
1962 // never includes any spacing
1963 gfxFloat mPartAdvance
;
1964 // appunits width of the ligature part; includes before-spacing
1965 // when the part is at the start of the ligature, and after-spacing
1966 // when the part is as the end of the ligature
1967 gfxFloat mPartWidth
;
1969 PRPackedBool mClipBeforePart
;
1970 PRPackedBool mClipAfterPart
;
1973 // user font set generation when text run was created
1974 PRUint64
GetUserFontSetGeneration() { return mUserFontSetGeneration
; }
1977 // number of entries referencing this textrun in the gfxTextRunWordCache
1978 PRUint32 mCachedWords
;
1979 // generation of gfxTextRunWordCache that refers to this textrun;
1980 // if the cache gets cleared, then mCachedWords is no longer meaningful
1981 PRUint32 mCacheGeneration
;
1983 void Dump(FILE* aOutput
);
1986 // post-process glyph advances to deal with synthetic bolding
1987 void AdjustAdvancesForSyntheticBold(PRUint32 aStart
, PRUint32 aLength
);
1991 * Initializes the textrun to blank.
1992 * @param aGlyphStorage preallocated array of CompressedGlyph[aLength]
1993 * for the textrun to use; if aText is not persistent, then it has also
1994 * been appended to this array, so it must NOT be freed separately.
1996 gfxTextRun(const gfxTextRunFactory::Parameters
*aParams
, const void *aText
,
1997 PRUint32 aLength
, gfxFontGroup
*aFontGroup
, PRUint32 aFlags
,
1998 CompressedGlyph
*aGlyphStorage
);
2001 * Helper for the Create() factory method to allocate the required
2002 * glyph storage, and copy the text (modifying the aText parameter)
2003 * if it is not flagged as persistent.
2005 static CompressedGlyph
* AllocateStorage(const void*& aText
,
2010 // **** general helpers ****
2012 // Allocate aCount DetailedGlyphs for the given index
2013 DetailedGlyph
*AllocateDetailedGlyphs(PRUint32 aCharIndex
, PRUint32 aCount
);
2015 // Get the total advance for a range of glyphs.
2016 PRInt32
GetAdvanceForGlyphs(PRUint32 aStart
, PRUint32 aEnd
);
2018 // Spacing for characters outside the range aSpacingStart/aSpacingEnd
2019 // is assumed to be zero; such characters are not passed to aProvider.
2020 // This is useful to protect aProvider from being passed character indices
2021 // it is not currently able to handle.
2022 PRBool
GetAdjustedSpacingArray(PRUint32 aStart
, PRUint32 aEnd
,
2023 PropertyProvider
*aProvider
,
2024 PRUint32 aSpacingStart
, PRUint32 aSpacingEnd
,
2025 nsTArray
<PropertyProvider::Spacing
> *aSpacing
);
2027 // **** ligature helpers ****
2028 // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
2029 // to handle requests that begin or end inside a ligature)
2031 // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
2032 LigatureData
ComputeLigatureData(PRUint32 aPartStart
, PRUint32 aPartEnd
,
2033 PropertyProvider
*aProvider
);
2034 gfxFloat
ComputePartialLigatureWidth(PRUint32 aPartStart
, PRUint32 aPartEnd
,
2035 PropertyProvider
*aProvider
);
2036 void DrawPartialLigature(gfxFont
*aFont
, gfxContext
*aCtx
,
2037 PRUint32 aStart
, PRUint32 aEnd
, gfxPoint
*aPt
,
2038 PropertyProvider
*aProvider
);
2039 // Advance aStart to the start of the nearest ligature; back up aEnd
2040 // to the nearest ligature end; may result in *aStart == *aEnd
2041 void ShrinkToLigatureBoundaries(PRUint32
*aStart
, PRUint32
*aEnd
);
2042 // result in appunits
2043 gfxFloat
GetPartialLigatureWidth(PRUint32 aStart
, PRUint32 aEnd
, PropertyProvider
*aProvider
);
2044 void AccumulatePartialLigatureMetrics(gfxFont
*aFont
,
2045 PRUint32 aStart
, PRUint32 aEnd
,
2046 gfxFont::BoundingBoxType aBoundingBoxType
,
2047 gfxContext
*aRefContext
,
2048 PropertyProvider
*aProvider
,
2051 // **** measurement helper ****
2052 void AccumulateMetricsForRun(gfxFont
*aFont
, PRUint32 aStart
, PRUint32 aEnd
,
2053 gfxFont::BoundingBoxType aBoundingBoxType
,
2054 gfxContext
*aRefContext
,
2055 PropertyProvider
*aProvider
,
2056 PRUint32 aSpacingStart
, PRUint32 aSpacingEnd
,
2059 // **** drawing helper ****
2060 void DrawGlyphs(gfxFont
*aFont
, gfxContext
*aContext
, PRBool aDrawToPath
,
2061 gfxPoint
*aPt
, PRUint32 aStart
, PRUint32 aEnd
,
2062 PropertyProvider
*aProvider
,
2063 PRUint32 aSpacingStart
, PRUint32 aSpacingEnd
);
2065 // All our glyph data is in logical order, not visual.
2066 // mCharacterGlyphs is allocated by the factory that creates the textrun,
2067 // to avoid the possibility of failure during the constructor;
2068 // however, ownership passes to the textrun during construction and so
2069 // it must be deleted in the destructor.
2070 CompressedGlyph
* mCharacterGlyphs
;
2072 // For characters whose glyph data does not fit the "simple" glyph criteria
2073 // in CompressedGlyph, we use a sorted array to store the association
2074 // between the source character offset and an index into an array
2075 // DetailedGlyphs. The CompressedGlyph record includes a count of
2076 // the number of DetailedGlyph records that belong to the character,
2077 // starting at the given index.
2078 class DetailedGlyphStore
{
2080 DetailedGlyphStore()
2084 // This is optimized for the most common calling patterns:
2085 // we rarely need random access to the records, access is most commonly
2086 // sequential through the textRun, so we record the last-used index
2087 // and check whether the caller wants the same record again, or the
2088 // next; if not, it's most likely we're starting over from the start
2089 // of the run, so we check the first entry before resorting to binary
2090 // search as a last resort.
2091 // NOTE that this must not be called for a character offset that does
2092 // not have any DetailedGlyph records; callers must have verified that
2093 // mCharacterGlyphs[aOffset].GetGlyphCount() is greater than zero
2094 // before calling this, otherwise the assertions here will fire (in a
2095 // debug build), and we'll probably crash.
2096 DetailedGlyph
* Get(PRUint32 aOffset
) {
2097 NS_ASSERTION(mOffsetToIndex
.Length() > 0,
2098 "no detailed glyph records!");
2099 DetailedGlyph
* details
= mDetails
.Elements();
2100 // check common cases (fwd iteration, initial entry, etc) first
2101 if (mLastUsed
< mOffsetToIndex
.Length() - 1 &&
2102 aOffset
== mOffsetToIndex
[mLastUsed
+ 1].mOffset
) {
2104 } else if (aOffset
== mOffsetToIndex
[0].mOffset
) {
2106 } else if (aOffset
== mOffsetToIndex
[mLastUsed
].mOffset
) {
2108 } else if (mLastUsed
> 0 &&
2109 aOffset
== mOffsetToIndex
[mLastUsed
- 1].mOffset
) {
2113 mOffsetToIndex
.BinaryIndexOf(aOffset
, CompareToOffset());
2115 NS_ASSERTION(mLastUsed
!= nsTArray
<DGRec
>::NoIndex
,
2116 "detailed glyph record missing!");
2117 return details
+ mOffsetToIndex
[mLastUsed
].mIndex
;
2120 DetailedGlyph
* Allocate(PRUint32 aOffset
, PRUint32 aCount
) {
2121 PRUint32 detailIndex
= mDetails
.Length();
2122 DetailedGlyph
*details
= mDetails
.AppendElements(aCount
);
2126 // We normally set up glyph records sequentially, so the common case
2127 // here is to append new records to the mOffsetToIndex array;
2128 // test for that before falling back to the InsertElementSorted
2130 if (mOffsetToIndex
.Length() == 0 ||
2131 aOffset
> mOffsetToIndex
[mOffsetToIndex
.Length() - 1].mOffset
) {
2132 if (!mOffsetToIndex
.AppendElement(DGRec(aOffset
, detailIndex
))) {
2136 if (!mOffsetToIndex
.InsertElementSorted(DGRec(aOffset
, detailIndex
),
2137 CompareRecordOffsets())) {
2146 DGRec(const PRUint32
& aOffset
, const PRUint32
& aIndex
)
2147 : mOffset(aOffset
), mIndex(aIndex
) { }
2148 PRUint32 mOffset
; // source character offset in the textrun
2149 PRUint32 mIndex
; // index where this char's DetailedGlyphs begin
2152 struct CompareToOffset
{
2153 PRBool
Equals(const DGRec
& a
, const PRUint32
& b
) const {
2154 return a
.mOffset
== b
;
2156 PRBool
LessThan(const DGRec
& a
, const PRUint32
& b
) const {
2157 return a
.mOffset
< b
;
2161 struct CompareRecordOffsets
{
2162 PRBool
Equals(const DGRec
& a
, const DGRec
& b
) const {
2163 return a
.mOffset
== b
.mOffset
;
2165 PRBool
LessThan(const DGRec
& a
, const DGRec
& b
) const {
2166 return a
.mOffset
< b
.mOffset
;
2170 // Concatenated array of all the DetailedGlyph records needed for the
2171 // textRun; individual character offsets are associated with indexes
2172 // into this array via the mOffsetToIndex table.
2173 nsTArray
<DetailedGlyph
> mDetails
;
2175 // For each character offset that needs DetailedGlyphs, we record the
2176 // index in mDetails where the list of glyphs begins. This array is
2177 // sorted by mOffset.
2178 nsTArray
<DGRec
> mOffsetToIndex
;
2180 // Records the most recently used index into mOffsetToIndex, so that
2181 // we can support sequential access more quickly than just doing
2182 // a binary search each time.
2183 nsTArray
<DGRec
>::index_type mLastUsed
;
2186 nsAutoPtr
<DetailedGlyphStore
> mDetailedGlyphs
;
2188 // XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*,
2189 // for smaller size especially in the super-common one-glyphrun case
2190 nsAutoTArray
<GlyphRun
,1> mGlyphRuns
;
2191 // When TEXT_IS_8BIT is set, we use mSingle, otherwise we use mDouble.
2192 // When TEXT_IS_PERSISTENT is set, we don't own the text, otherwise we
2193 // own the text. When we own the text, it's allocated fused with the
2194 // mCharacterGlyphs array, and therefore need not be explicitly deleted.
2195 // This text is not null-terminated.
2197 const PRUint8
*mSingle
;
2198 const PRUnichar
*mDouble
;
2201 gfxFontGroup
*mFontGroup
; // addrefed
2202 gfxSkipChars mSkipChars
;
2203 nsExpirationState mExpirationState
;
2204 PRUint32 mAppUnitsPerDevUnit
;
2206 PRUint32 mCharacterCount
;
2208 PRUint64 mUserFontSetGeneration
; // user font set generation when text run created
2210 PRBool mSkipDrawing
; // true if the font group we used had a user font
2211 // download that's in progress, so we should hide text
2212 // until the download completes (or timeout fires)
2215 class THEBES_API gfxFontGroup
: public gfxTextRunFactory
{
2217 static void Shutdown(); // platform must call this to release the languageAtomService
2219 gfxFontGroup(const nsAString
& aFamilies
, const gfxFontStyle
*aStyle
, gfxUserFontSet
*aUserFontSet
= nsnull
);
2221 virtual ~gfxFontGroup();
2223 virtual gfxFont
*GetFontAt(PRInt32 i
) {
2224 // If it turns out to be hard for all clients that cache font
2225 // groups to call UpdateFontList at appropriate times, we could
2226 // instead consider just calling UpdateFontList from someplace
2227 // more central (such as here).
2228 NS_ASSERTION(!mUserFontSet
|| mCurrGeneration
== GetGeneration(),
2229 "Whoever was caching this font group should have "
2230 "called UpdateFontList on it");
2231 NS_ASSERTION(mFonts
.Length() > PRUint32(i
),
2232 "Requesting a font index that doesn't exist");
2234 return static_cast<gfxFont
*>(mFonts
[i
]);
2236 virtual PRUint32
FontListLength() const {
2237 return mFonts
.Length();
2240 PRBool
Equals(const gfxFontGroup
& other
) const {
2241 return mFamilies
.Equals(other
.mFamilies
) &&
2242 mStyle
.Equals(other
.mStyle
);
2245 const gfxFontStyle
*GetStyle() const { return &mStyle
; }
2247 virtual gfxFontGroup
*Copy(const gfxFontStyle
*aStyle
);
2250 * The listed characters should not be passed in to MakeTextRun and should
2251 * be treated as invisible and zero-width.
2253 static PRBool
IsInvalidChar(PRUnichar ch
);
2256 * Make a textrun for an empty string. This is fast; if you call it,
2257 * don't bother caching the result.
2259 gfxTextRun
*MakeEmptyTextRun(const Parameters
*aParams
, PRUint32 aFlags
);
2261 * Make a textrun for a single ASCII space. This is fast; if you call it,
2262 * don't bother caching the result.
2264 gfxTextRun
*MakeSpaceTextRun(const Parameters
*aParams
, PRUint32 aFlags
);
2267 * Make a textrun for a given string.
2268 * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
2269 * textrun will copy it.
2270 * This calls FetchGlyphExtents on the textrun.
2272 virtual gfxTextRun
*MakeTextRun(const PRUnichar
*aString
, PRUint32 aLength
,
2273 const Parameters
*aParams
, PRUint32 aFlags
);
2275 * Make a textrun for a given string.
2276 * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
2277 * textrun will copy it.
2278 * This calls FetchGlyphExtents on the textrun.
2280 virtual gfxTextRun
*MakeTextRun(const PRUint8
*aString
, PRUint32 aLength
,
2281 const Parameters
*aParams
, PRUint32 aFlags
);
2283 /* helper function for splitting font families on commas and
2284 * calling a function for each family to fill the mFonts array
2286 typedef PRBool (*FontCreationCallback
) (const nsAString
& aName
,
2287 const nsACString
& aGenericName
,
2289 PRBool
ForEachFont(const nsAString
& aFamilies
,
2291 FontCreationCallback fc
,
2293 PRBool
ForEachFont(FontCreationCallback fc
, void *closure
);
2296 * Check whether a given font (specified by its gfxFontEntry)
2297 * is already in the fontgroup's list of actual fonts
2299 PRBool
HasFont(const gfxFontEntry
*aFontEntry
);
2301 const nsString
& GetFamilies() { return mFamilies
; }
2303 // This returns the preferred underline for this font group.
2304 // Some CJK fonts have wrong underline offset in its metrics.
2305 // If this group has such "bad" font, each platform's gfxFontGroup initialized mUnderlineOffset.
2306 // The value should be lower value of first font's metrics and the bad font's metrics.
2307 // Otherwise, this returns from first font's metrics.
2308 enum { UNDERLINE_OFFSET_NOT_SET
= PR_INT16_MAX
};
2309 virtual gfxFloat
GetUnderlineOffset() {
2310 if (mUnderlineOffset
== UNDERLINE_OFFSET_NOT_SET
)
2311 mUnderlineOffset
= GetFontAt(0)->GetMetrics().underlineOffset
;
2312 return mUnderlineOffset
;
2315 virtual already_AddRefed
<gfxFont
>
2316 FindFontForChar(PRUint32 ch
, PRUint32 prevCh
, PRInt32 aRunScript
,
2317 gfxFont
*aPrevMatchedFont
);
2319 // search through pref fonts for a character, return nsnull if no matching pref font
2320 virtual already_AddRefed
<gfxFont
> WhichPrefFontSupportsChar(PRUint32 aCh
);
2322 virtual already_AddRefed
<gfxFont
> WhichSystemFontSupportsChar(PRUint32 aCh
);
2324 void ComputeRanges(nsTArray
<gfxTextRange
>& mRanges
,
2325 const PRUnichar
*aString
, PRUint32 begin
, PRUint32 end
,
2326 PRInt32 aRunScript
);
2328 gfxUserFontSet
* GetUserFontSet();
2330 // With downloadable fonts, the composition of the font group can change as fonts are downloaded
2331 // for each change in state of the user font set, the generation value is bumped to avoid picking up
2332 // previously created text runs in the text run word cache. For font groups based on stylesheets
2333 // with no @font-face rule, this always returns 0.
2334 PRUint64
GetGeneration();
2336 // If there is a user font set, check to see whether the font list or any
2337 // caches need updating.
2338 virtual void UpdateFontList();
2340 PRBool
ShouldSkipDrawing() const {
2341 return mSkipDrawing
;
2346 gfxFontStyle mStyle
;
2347 nsTArray
< nsRefPtr
<gfxFont
> > mFonts
;
2348 gfxFloat mUnderlineOffset
;
2350 gfxUserFontSet
* mUserFontSet
;
2351 PRUint64 mCurrGeneration
; // track the current user font set generation, rebuild font list if needed
2353 // cache the most recent pref font to avoid general pref font lookup
2354 nsRefPtr
<gfxFontFamily
> mLastPrefFamily
;
2355 nsRefPtr
<gfxFont
> mLastPrefFont
;
2356 eFontPrefLang mLastPrefLang
; // lang group for last pref font
2357 eFontPrefLang mPageLang
;
2358 PRPackedBool mLastPrefFirstFont
; // is this the first font in the list of pref fonts for this lang group?
2360 PRPackedBool mSkipDrawing
; // hide text while waiting for a font
2361 // download to complete (or fallback
2364 // Used for construction/destruction. Not intended to change the font set
2365 // as invalidation of font lists and caches is not considered.
2366 void SetUserFontSet(gfxUserFontSet
*aUserFontSet
);
2368 // Initialize the list of fonts
2369 void BuildFontList();
2371 // Init this font group's font metrics. If there no bad fonts, you don't need to call this.
2372 // But if there are one or more bad fonts which have bad underline offset,
2373 // you should call this with the *first* bad font.
2374 void InitMetricsForBadFont(gfxFont
* aBadFont
);
2376 // Set up the textrun glyphs for an entire text run:
2377 // find script runs, and then call InitScriptRun for each
2378 void InitTextRun(gfxContext
*aContext
,
2379 gfxTextRun
*aTextRun
,
2380 const PRUnichar
*aString
,
2383 // InitTextRun helper to handle a single script run, by finding font ranges
2384 // and calling each font's InitTextRun() as appropriate
2385 void InitScriptRun(gfxContext
*aContext
,
2386 gfxTextRun
*aTextRun
,
2387 const PRUnichar
*aString
,
2388 PRUint32 aTotalLength
,
2389 PRUint32 aScriptRunStart
,
2390 PRUint32 aScriptRunEnd
,
2391 PRInt32 aRunScript
);
2393 /* If aResolveGeneric is true, then CSS/Gecko generic family names are
2394 * replaced with preferred fonts.
2396 * If aResolveFontName is true then fc() is called only for existing fonts
2397 * and with actual font names. If false then fc() is called with each
2398 * family name in aFamilies (after resolving CSS/Gecko generic family names
2399 * if aResolveGeneric).
2401 PRBool
ForEachFontInternal(const nsAString
& aFamilies
,
2403 PRBool aResolveGeneric
,
2404 PRBool aResolveFontName
,
2405 FontCreationCallback fc
,
2408 static PRBool
FontResolverProc(const nsAString
& aName
, void *aClosure
);
2410 static PRBool
FindPlatformFont(const nsAString
& aName
,
2411 const nsACString
& aGenericName
,
2414 static NS_HIDDEN_(nsILanguageAtomService
*) gLangService
;