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 "nsClassHashtable.h"
52 #include "nsHashKeys.h"
53 #include "gfxSkipChars.h"
55 #include "nsExpirationTracker.h"
56 #include "gfxFontConstants.h"
57 #include "gfxPlatform.h"
59 #include "nsISupportsImpl.h"
71 class gfxUserFontData
;
73 class nsILanguageAtomService
;
75 typedef struct _hb_blob_t hb_blob_t
;
77 // We should eliminate these synonyms when it won't cause many merge conflicts.
78 #define FONT_STYLE_NORMAL NS_FONT_STYLE_NORMAL
79 #define FONT_STYLE_ITALIC NS_FONT_STYLE_ITALIC
80 #define FONT_STYLE_OBLIQUE NS_FONT_STYLE_OBLIQUE
82 // We should eliminate these synonyms when it won't cause many merge conflicts.
83 #define FONT_WEIGHT_NORMAL NS_FONT_WEIGHT_NORMAL
84 #define FONT_WEIGHT_BOLD NS_FONT_WEIGHT_BOLD
86 #define FONT_MAX_SIZE 2000.0
88 #define NO_FONT_LANGUAGE_OVERRIDE 0
90 // An OpenType feature tag and value pair
91 struct THEBES_API gfxFontFeature
{
92 PRUint32 mTag
; // see http://www.microsoft.com/typography/otspec/featuretags.htm
93 PRUint32 mValue
; // 0 = off, 1 = on, larger values may be used as parameters
94 // to features that select among multiple alternatives
98 operator<(const gfxFontFeature
& a
, const gfxFontFeature
& b
)
100 return (a
.mTag
< b
.mTag
) || ((a
.mTag
== b
.mTag
) && (a
.mValue
< b
.mValue
));
104 operator==(const gfxFontFeature
& a
, const gfxFontFeature
& b
)
106 return (a
.mTag
== b
.mTag
) && (a
.mValue
== b
.mValue
);
110 struct THEBES_API gfxFontStyle
{
112 gfxFontStyle(PRUint8 aStyle
, PRUint16 aWeight
, PRInt16 aStretch
,
113 gfxFloat aSize
, nsIAtom
*aLanguage
,
114 float aSizeAdjust
, PRPackedBool aSystemFont
,
115 PRPackedBool aFamilyNameQuirks
,
116 PRPackedBool aPrinterFont
,
117 const nsString
& aFeatureSettings
,
118 const nsString
& aLanguageOverride
);
119 gfxFontStyle(const gfxFontStyle
& aStyle
);
122 delete featureSettings
;
125 // The style of font (normal, italic, oblique)
128 // Say that this font is a system font and therefore does not
129 // require certain fixup that we do for fonts from untrusted
131 PRPackedBool systemFont
: 1;
133 // Say that this font is used for print or print preview.
134 PRPackedBool printerFont
: 1;
136 // True if the character set quirks (for treatment of "Symbol",
137 // "Wingdings", etc.) should be applied.
138 PRPackedBool familyNameQuirks
: 1;
140 // The weight of the font. 100, 200, ... 900 are the weights, and
141 // single integer offsets request the next bolder/lighter font
142 // available. For example, for a font available in weights 200,
143 // 400, 700, and 900, a weight of 898 should lead to the weight 400
144 // font being used, since it is two weights lighter than 900.
147 // The stretch of the font (the sum of various NS_FONT_STRETCH_*
148 // constants; see gfxFontConstants.h).
151 // The logical size of the font, in pixels
154 // The aspect-value (ie., the ratio actualsize:actualxheight) that any
155 // actual physical font created from this font structure must have when
156 // rendering or measuring a string. A value of 0 means no adjustment
160 // the language (may be an internal langGroup code rather than an actual
161 // language code) specified in the document or element's lang property,
162 // or inferred from the charset
165 // Language system tag, to override document language;
166 // an OpenType "language system" tag represented as a 32-bit integer
167 // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
168 // Normally 0, so font rendering will use the document or element language
169 // (see above) to control any language-specific rendering, but the author
170 // can override this for cases where the options implemented in the font
171 // do not directly match the actual language. (E.g. lang may be Macedonian,
172 // but the font in use does not explicitly support this; the author can
173 // use font-language-override to request the Serbian option in the font
174 // in order to get correct glyph shapes.)
175 PRUint32 languageOverride
;
177 // custom opentype feature settings
178 nsTArray
<gfxFontFeature
> *featureSettings
;
180 // Return the final adjusted font size for the given aspect ratio.
181 // Not meant to be called when sizeAdjust = 0.
182 gfxFloat
GetAdjustedSize(gfxFloat aspect
) const {
183 NS_ASSERTION(sizeAdjust
!= 0.0, "Not meant to be called when sizeAdjust = 0");
184 gfxFloat adjustedSize
= PR_MAX(NS_round(size
*(sizeAdjust
/aspect
)), 1.0);
185 return PR_MIN(adjustedSize
, FONT_MAX_SIZE
);
188 PLDHashNumber
Hash() const {
189 return ((style
+ (systemFont
<< 7) + (familyNameQuirks
<< 8) +
190 (weight
<< 9)) + PRUint32(size
*1000) + PRUint32(sizeAdjust
*1000)) ^
191 nsISupportsHashKey::HashKey(language
);
194 void ComputeWeightAndOffset(PRInt8
*outBaseWeight
,
195 PRInt8
*outOffset
) const;
197 PRBool
Equals(const gfxFontStyle
& other
) const {
198 return (size
== other
.size
) &&
199 (style
== other
.style
) &&
200 (systemFont
== other
.systemFont
) &&
201 (printerFont
== other
.printerFont
) &&
202 (familyNameQuirks
== other
.familyNameQuirks
) &&
203 (weight
== other
.weight
) &&
204 (stretch
== other
.stretch
) &&
205 (language
== other
.language
) &&
206 (sizeAdjust
== other
.sizeAdjust
) &&
207 ((!featureSettings
&& !other
.featureSettings
) ||
208 (featureSettings
&& other
.featureSettings
&&
209 (*featureSettings
== *other
.featureSettings
))) &&
210 (languageOverride
== other
.languageOverride
);
213 static void ParseFontFeatureSettings(const nsString
& aFeatureString
,
214 nsTArray
<gfxFontFeature
>& aFeatures
);
216 static PRUint32
ParseFontLanguageOverride(const nsString
& aLangTag
);
221 NS_INLINE_DECL_REFCOUNTING(gfxFontEntry
)
223 gfxFontEntry(const nsAString
& aName
, gfxFontFamily
*aFamily
= nsnull
,
224 PRBool aIsStandardFace
= PR_FALSE
) :
225 mName(aName
), mItalic(PR_FALSE
), mFixedPitch(PR_FALSE
),
226 mIsProxy(PR_FALSE
), mIsValid(PR_TRUE
),
227 mIsBadUnderlineFont(PR_FALSE
), mIsUserFont(PR_FALSE
),
228 mIsLocalUserFont(PR_FALSE
), mStandardFace(aIsStandardFace
),
229 mSymbolFont(PR_FALSE
),
230 mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL
),
231 mHasCmapTable(PR_FALSE
),
232 mCmapInitialized(PR_FALSE
),
233 mUVSOffset(0), mUVSData(nsnull
),
234 mUserFontData(nsnull
),
235 mFeatureSettings(nsnull
),
236 mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE
),
240 virtual ~gfxFontEntry();
242 // unique name for the face, *not* the family
243 const nsString
& Name() const { return mName
; }
245 PRUint16
Weight() const { return mWeight
; }
246 PRInt16
Stretch() const { return mStretch
; }
248 PRBool
IsUserFont() const { return mIsUserFont
; }
249 PRBool
IsLocalUserFont() const { return mIsLocalUserFont
; }
250 PRBool
IsFixedPitch() const { return mFixedPitch
; }
251 PRBool
IsItalic() const { return mItalic
; }
252 PRBool
IsBold() const { return mWeight
>= 600; } // bold == weights 600 and above
253 PRBool
IsSymbolFont() const { return mSymbolFont
; }
255 inline PRBool
HasCmapTable() {
256 if (!mCmapInitialized
) {
259 return mHasCmapTable
;
262 inline PRBool
HasCharacter(PRUint32 ch
) {
263 if (mCharacterMap
.test(ch
))
266 return TestCharacterMap(ch
);
269 virtual PRBool
SkipDuringSystemFallback() { return PR_FALSE
; }
270 virtual PRBool
TestCharacterMap(PRUint32 aCh
);
271 nsresult
InitializeUVSMap();
272 PRUint16
GetUVSGlyph(PRUint32 aCh
, PRUint32 aVS
);
273 virtual nsresult
ReadCMAP();
275 virtual PRBool
MatchesGenericFamily(const nsACString
& aGeneric
) const {
278 virtual PRBool
SupportsLangGroup(nsIAtom
*aLangGroup
) const {
282 virtual nsresult
GetFontTable(PRUint32 aTableTag
, nsTArray
<PRUint8
>& aBuffer
) {
283 return NS_ERROR_FAILURE
; // all platform subclasses should reimplement this!
286 void SetFamily(gfxFontFamily
* aFamily
) {
290 const nsString
& FamilyName() const;
292 already_AddRefed
<gfxFont
> FindOrMakeFont(const gfxFontStyle
*aStyle
,
295 // Subclasses should override this if they can do something more efficient
296 // than getting tables with GetFontTable() and caching them in the entry.
298 // Note that some gfxFont implementations may not call this at all,
299 // if it is more efficient to get the table from the OS at that level.
300 virtual hb_blob_t
*GetFontTable(PRUint32 aTag
);
304 PRPackedBool mItalic
: 1;
305 PRPackedBool mFixedPitch
: 1;
306 PRPackedBool mIsProxy
: 1;
307 PRPackedBool mIsValid
: 1;
308 PRPackedBool mIsBadUnderlineFont
: 1;
309 PRPackedBool mIsUserFont
: 1;
310 PRPackedBool mIsLocalUserFont
: 1;
311 PRPackedBool mStandardFace
: 1;
312 PRPackedBool mSymbolFont
: 1;
317 PRPackedBool mHasCmapTable
;
318 PRPackedBool mCmapInitialized
;
319 gfxSparseBitSet mCharacterMap
;
321 nsAutoArrayPtr
<PRUint8
> mUVSData
;
322 gfxUserFontData
* mUserFontData
;
324 nsTArray
<gfxFontFeature
> *mFeatureSettings
;
325 PRUint32 mLanguageOverride
;
328 friend class gfxPlatformFontList
;
329 friend class gfxMacPlatformFontList
;
330 friend class gfxFcFontEntry
;
331 friend class gfxFontFamily
;
332 friend class gfxSingleFaceMacFontFamily
;
335 mItalic(PR_FALSE
), mFixedPitch(PR_FALSE
),
336 mIsProxy(PR_FALSE
), mIsValid(PR_TRUE
),
337 mIsBadUnderlineFont(PR_FALSE
),
338 mIsUserFont(PR_FALSE
),
339 mIsLocalUserFont(PR_FALSE
),
340 mStandardFace(PR_FALSE
),
341 mSymbolFont(PR_FALSE
),
342 mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL
),
343 mHasCmapTable(PR_FALSE
),
344 mCmapInitialized(PR_FALSE
),
345 mUVSOffset(0), mUVSData(nsnull
),
346 mUserFontData(nsnull
),
347 mFeatureSettings(nsnull
),
348 mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE
),
352 virtual gfxFont
*CreateFontInstance(const gfxFontStyle
*aFontStyle
, PRBool aNeedsBold
) {
353 NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
357 gfxFontFamily
*mFamily
;
360 * Font table cache, to support GetFontTable for harfbuzz.
362 * The harfbuzz shaper (and potentially other clients) needs access to raw
363 * font table data. This needs to be cached so that it can be used
364 * repeatedly (each time we construct a text run; in some cases, for
365 * each character/glyph within the run) without re-fetching large tables
368 * Because we may instantiate many gfxFonts for the same physical font
369 * file (at different sizes), we should ensure that they can share a
370 * single cached copy of the font tables. To do this, we implement table
371 * access and caching on the fontEntry rather than the font itself.
373 * The default implementation uses GetFontTable() to read font table
374 * data into byte arrays, and caches these in a hashtable along with
375 * hb_blob_t wrappers. The entry can then return blobs to harfbuzz.
377 * Harfbuzz will "destroy" the blobs when it is finished with them;
378 * they are created with a destroy callback that removes them from
379 * the hashtable when all references are released.
381 class FontTableCacheEntry
{
383 // create a cache entry by adopting the content of an existing buffer
384 FontTableCacheEntry(nsTArray
<PRUint8
>& aBuffer
,
386 nsClassHashtable
<nsUint32HashKey
,FontTableCacheEntry
>& aCache
);
388 ~FontTableCacheEntry() {
389 MOZ_COUNT_DTOR(FontTableCacheEntry
);
392 hb_blob_t
*GetBlob() const { return mBlob
; }
395 // the data block, owned (via adoption) by the entry
396 nsTArray
<PRUint8
> mData
;
397 // a harfbuzz blob wrapper that we can return to clients
399 // the blob destroy function needs to know the table tag
400 // and the owning hashtable, so that it can remove the entry
402 nsClassHashtable
<nsUint32HashKey
,FontTableCacheEntry
>&
407 FontTableCacheEntry(const FontTableCacheEntry
&);
409 static void Destroy(void *aUserData
);
412 nsClassHashtable
<nsUint32HashKey
,FontTableCacheEntry
> mFontTableCache
;
415 gfxFontEntry(const gfxFontEntry
&);
416 gfxFontEntry
& operator=(const gfxFontEntry
&);
420 // used when picking fallback font
422 FontSearch(const PRUint32 aCharacter
, gfxFont
*aFont
) :
423 mCh(aCharacter
), mFontToMatch(aFont
), mMatchRank(0) {
426 gfxFont
* mFontToMatch
;
428 nsRefPtr
<gfxFontEntry
> mBestMatch
;
431 class gfxFontFamily
{
433 NS_INLINE_DECL_REFCOUNTING(gfxFontFamily
)
435 gfxFontFamily(const nsAString
& aName
) :
437 mOtherFamilyNamesInitialized(PR_FALSE
),
438 mHasOtherFamilyNames(PR_FALSE
),
439 mFaceNamesInitialized(PR_FALSE
),
440 mHasStyles(PR_FALSE
),
441 mIsSimpleFamily(PR_FALSE
),
442 mIsBadUnderlineFamily(PR_FALSE
)
445 virtual ~gfxFontFamily() { }
447 const nsString
& Name() { return mName
; }
449 virtual void LocalizedName(nsAString
& aLocalizedName
);
450 virtual PRBool
HasOtherFamilyNames();
452 nsTArray
<nsRefPtr
<gfxFontEntry
> >& GetFontList() { return mAvailableFonts
; }
454 void AddFontEntry(nsRefPtr
<gfxFontEntry
> aFontEntry
) {
455 mAvailableFonts
.AppendElement(aFontEntry
);
458 // note that the styles for this family have been added
459 void SetHasStyles(PRBool aHasStyles
) { mHasStyles
= aHasStyles
; }
461 // choose a specific face to match a style using CSS font matching
462 // rules (weight matching occurs here). may return a face that doesn't
463 // precisely match (e.g. normal face when no italic face exists).
464 // aNeedsSyntheticBold is set to true when synthetic bolding is
465 // needed, false otherwise
466 gfxFontEntry
*FindFontForStyle(const gfxFontStyle
& aFontStyle
,
467 PRBool
& aNeedsSyntheticBold
);
469 // iterates over faces looking for a match with a given characters
470 // used as part of the font fallback process
471 void FindFontForChar(FontSearch
*aMatchData
);
473 // read in other family names, if any, and use functor to add each into cache
474 virtual void ReadOtherFamilyNames(gfxPlatformFontList
*aPlatformFontList
);
476 // read in other localized family names, fullnames and Postscript names
477 // for all faces and append to lookup tables
478 virtual void ReadFaceNames(gfxPlatformFontList
*aPlatformFontList
,
479 PRBool aNeedFullnamePostscriptNames
);
481 // find faces belonging to this family (platform implementations override this;
482 // should be made pure virtual once all subclasses have been updated)
483 virtual void FindStyleVariations() { }
485 // search for a specific face using the Postscript name
486 gfxFontEntry
* FindFont(const nsAString
& aPostscriptName
);
488 // read in cmaps for all the faces
490 PRUint32 i
, numFonts
= mAvailableFonts
.Length();
491 // called from RunLoader BEFORE CheckForSimpleFamily so that there cannot
492 // be any NULL entries in mAvailableFonts
493 for (i
= 0; i
< numFonts
; i
++)
494 mAvailableFonts
[i
]->ReadCMAP();
497 // mark this family as being in the "bad" underline offset blacklist
498 void SetBadUnderlineFamily() {
499 mIsBadUnderlineFamily
= PR_TRUE
;
501 SetBadUnderlineFonts();
505 PRBool
IsBadUnderlineFamily() const { return mIsBadUnderlineFamily
; }
507 // sort available fonts to put preferred (standard) faces towards the end
508 void SortAvailableFonts();
510 // check whether the family fits into the simple 4-face model,
511 // so we can use simplified style-matching;
512 // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
513 void CheckForSimpleFamily();
516 // fills in an array with weights of faces that match style,
517 // returns whether any matching entries found
518 virtual PRBool
FindWeightsForStyle(gfxFontEntry
* aFontsForWeights
[],
519 PRBool anItalic
, PRInt16 aStretch
);
521 PRBool
ReadOtherFamilyNamesForFace(gfxPlatformFontList
*aPlatformFontList
,
522 nsTArray
<PRUint8
>& aNameTable
,
523 PRBool useFullName
= PR_FALSE
);
525 // set whether this font family is in "bad" underline offset blacklist.
526 void SetBadUnderlineFonts() {
527 PRUint32 i
, numFonts
= mAvailableFonts
.Length();
528 for (i
= 0; i
< numFonts
; i
++) {
529 if (mAvailableFonts
[i
]) {
530 mAvailableFonts
[i
]->mIsBadUnderlineFont
= PR_TRUE
;
536 nsTArray
<nsRefPtr
<gfxFontEntry
> > mAvailableFonts
;
537 PRPackedBool mOtherFamilyNamesInitialized
;
538 PRPackedBool mHasOtherFamilyNames
;
539 PRPackedBool mFaceNamesInitialized
;
540 PRPackedBool mHasStyles
;
541 PRPackedBool mIsSimpleFamily
;
542 PRPackedBool mIsBadUnderlineFamily
;
545 // for "simple" families, the faces are stored in mAvailableFonts
546 // with fixed positions:
547 kRegularFaceIndex
= 0,
549 kItalicFaceIndex
= 2,
550 kBoldItalicFaceIndex
= 3,
551 // mask values for selecting face with bold and/or italic attributes
557 struct gfxTextRange
{
558 gfxTextRange(PRUint32 aStart
, PRUint32 aEnd
) : start(aStart
), end(aEnd
) { }
559 PRUint32
Length() const { return end
- start
; }
560 nsRefPtr
<gfxFont
> font
;
568 * The mFonts hashtable contains most fonts, indexed by (gfxFontEntry*, style).
569 * It does not add a reference to the fonts it contains.
570 * When a font's refcount decreases to zero, instead of deleting it we
571 * add it to our expiration tracker.
572 * The expiration tracker tracks fonts with zero refcount. After a certain
573 * period of time, such fonts expire and are deleted.
575 * We're using 3 generations with a ten-second generation interval, so
576 * zero-refcount fonts will be deleted 20-30 seconds after their refcount
577 * goes to zero, if timer events fire in a timely manner.
579 class THEBES_API gfxFontCache
: public nsExpirationTracker
<gfxFont
,3> {
581 enum { TIMEOUT_SECONDS
= 10 };
583 : nsExpirationTracker
<gfxFont
,3>(TIMEOUT_SECONDS
*1000) { mFonts
.Init(); }
585 // Expire everything that has a zero refcount, so we don't leak them.
587 // All fonts should be gone.
588 NS_WARN_IF_FALSE(mFonts
.Count() == 0,
589 "Fonts still alive while shutting down gfxFontCache");
590 // Note that we have to delete everything through the expiration
591 // tracker, since there might be fonts not in the hashtable but in
596 * Get the global gfxFontCache. You must call Init() before
597 * calling this method --- the result will not be null.
599 static gfxFontCache
* GetCache() {
603 static nsresult
Init();
604 // It's OK to call this even if Init() has not been called.
605 static void Shutdown();
607 // Look up a font in the cache. Returns an addrefed pointer, or null
608 // if there's nothing matching in the cache
609 already_AddRefed
<gfxFont
> Lookup(const gfxFontEntry
*aFontEntry
,
610 const gfxFontStyle
*aFontGroup
);
611 // We created a new font (presumably because Lookup returned null);
612 // put it in the cache. The font's refcount should be nonzero. It is
613 // allowable to add a new font even if there is one already in the
614 // cache with the same key; we'll forget about the old one.
615 void AddNew(gfxFont
*aFont
);
617 // The font's refcount has gone to zero; give ownership of it to
618 // the cache. We delete it if it's not acquired again after a certain
620 void NotifyReleased(gfxFont
*aFont
);
622 // This gets called when the timeout has expired on a zero-refcount
623 // font; we just delete it.
624 virtual void NotifyExpired(gfxFont
*aFont
);
626 // Cleans out the hashtable and removes expired fonts waiting for cleanup.
627 // Other gfxFont objects may be still in use but they will be pushed
628 // into the expiration queues and removed.
635 void DestroyFont(gfxFont
*aFont
);
637 static gfxFontCache
*gGlobalCache
;
640 const gfxFontEntry
* mFontEntry
;
641 const gfxFontStyle
* mStyle
;
642 Key(const gfxFontEntry
* aFontEntry
, const gfxFontStyle
* aStyle
)
643 : mFontEntry(aFontEntry
), mStyle(aStyle
) {}
646 class HashEntry
: public PLDHashEntryHdr
{
648 typedef const Key
& KeyType
;
649 typedef const Key
* KeyTypePointer
;
651 // When constructing a new entry in the hashtable, we'll leave this
652 // blank. The caller of Put() will fill this in.
653 HashEntry(KeyTypePointer aStr
) : mFont(nsnull
) { }
654 HashEntry(const HashEntry
& toCopy
) : mFont(toCopy
.mFont
) { }
657 PRBool
KeyEquals(const KeyTypePointer aKey
) const;
658 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
659 static PLDHashNumber
HashKey(const KeyTypePointer aKey
) {
660 return NS_PTR_TO_INT32(aKey
->mFontEntry
) ^ aKey
->mStyle
->Hash();
662 enum { ALLOW_MEMMOVE
= PR_TRUE
};
667 nsTHashtable
<HashEntry
> mFonts
;
671 * This stores glyph bounds information for a particular gfxFont, at
672 * a particular appunits-per-dev-pixel ratio (because the compressed glyph
673 * width array is stored in appunits).
675 * We store a hashtable from glyph IDs to float bounding rects. For the
676 * common case where the glyph has no horizontal left bearing, and no
677 * y overflow above the font ascent or below the font descent, and tight
678 * bounding boxes are not required, we avoid storing the glyph ID in the hashtable
679 * and instead consult an array of 16-bit glyph XMost values (in appunits).
680 * This array always has an entry for the font's space glyph --- the width is
681 * assumed to be zero.
683 class THEBES_API gfxGlyphExtents
{
685 gfxGlyphExtents(PRUint32 aAppUnitsPerDevUnit
) :
686 mAppUnitsPerDevUnit(aAppUnitsPerDevUnit
) {
687 MOZ_COUNT_CTOR(gfxGlyphExtents
);
688 mTightGlyphExtents
.Init();
692 enum { INVALID_WIDTH
= 0xFFFF };
694 // returns INVALID_WIDTH => not a contained glyph
695 // Otherwise the glyph has no before-bearing or vertical bearings,
696 // and the result is its width measured from the baseline origin, in
698 PRUint16
GetContainedGlyphWidthAppUnits(PRUint32 aGlyphID
) const {
699 return mContainedGlyphWidths
.Get(aGlyphID
);
702 PRBool
IsGlyphKnown(PRUint32 aGlyphID
) const {
703 return mContainedGlyphWidths
.Get(aGlyphID
) != INVALID_WIDTH
||
704 mTightGlyphExtents
.GetEntry(aGlyphID
) != nsnull
;
707 PRBool
IsGlyphKnownWithTightExtents(PRUint32 aGlyphID
) const {
708 return mTightGlyphExtents
.GetEntry(aGlyphID
) != nsnull
;
711 // Get glyph extents; a rectangle relative to the left baseline origin
712 // Returns true on success. Can fail on OOM or when aContext is null
713 // and extents were not (successfully) prefetched.
714 PRBool
GetTightGlyphExtentsAppUnits(gfxFont
*aFont
, gfxContext
*aContext
,
715 PRUint32 aGlyphID
, gfxRect
*aExtents
);
717 void SetContainedGlyphWidthAppUnits(PRUint32 aGlyphID
, PRUint16 aWidth
) {
718 mContainedGlyphWidths
.Set(aGlyphID
, aWidth
);
720 void SetTightGlyphExtents(PRUint32 aGlyphID
, const gfxRect
& aExtentsAppUnits
);
722 PRUint32
GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit
; }
725 class HashEntry
: public nsUint32HashKey
{
727 // When constructing a new entry in the hashtable, we'll leave this
728 // blank. The caller of Put() will fill this in.
729 HashEntry(KeyTypePointer aPtr
) : nsUint32HashKey(aPtr
) {}
730 HashEntry(const HashEntry
& toCopy
) : nsUint32HashKey(toCopy
) {
731 x
= toCopy
.x
; y
= toCopy
.y
; width
= toCopy
.width
; height
= toCopy
.height
;
734 float x
, y
, width
, height
;
737 typedef PRUptrdiff PtrBits
;
738 enum { BLOCK_SIZE_BITS
= 7, BLOCK_SIZE
= 1 << BLOCK_SIZE_BITS
}; // 128-glyph blocks
742 void Set(PRUint32 aIndex
, PRUint16 aValue
);
743 PRUint16
Get(PRUint32 aIndex
) const {
744 PRUint32 block
= aIndex
>> BLOCK_SIZE_BITS
;
745 if (block
>= mBlocks
.Length())
746 return INVALID_WIDTH
;
747 PtrBits bits
= mBlocks
[block
];
749 return INVALID_WIDTH
;
750 PRUint32 indexInBlock
= aIndex
& (BLOCK_SIZE
- 1);
752 if (GetGlyphOffset(bits
) != indexInBlock
)
753 return INVALID_WIDTH
;
754 return GetWidth(bits
);
756 PRUint16
*widths
= reinterpret_cast<PRUint16
*>(bits
);
757 return widths
[indexInBlock
];
761 PRUint32
ComputeSize();
767 static PRUint32
GetGlyphOffset(PtrBits aBits
) {
768 NS_ASSERTION(aBits
& 0x1, "This is really a pointer...");
769 return (aBits
>> 1) & ((1 << BLOCK_SIZE_BITS
) - 1);
771 static PRUint32
GetWidth(PtrBits aBits
) {
772 NS_ASSERTION(aBits
& 0x1, "This is really a pointer...");
773 return aBits
>> (1 + BLOCK_SIZE_BITS
);
775 static PtrBits
MakeSingle(PRUint32 aGlyphOffset
, PRUint16 aWidth
) {
776 return (aWidth
<< (1 + BLOCK_SIZE_BITS
)) + (aGlyphOffset
<< 1) + 1;
779 nsTArray
<PtrBits
> mBlocks
;
782 GlyphWidths mContainedGlyphWidths
;
783 nsTHashtable
<HashEntry
> mTightGlyphExtents
;
784 PRUint32 mAppUnitsPerDevUnit
;
790 * This class implements text shaping (character to glyph mapping and
791 * glyph layout). There is a gfxFontShaper subclass for each text layout
792 * technology (uniscribe, core text, harfbuzz,....) we support.
794 * The shaper is responsible for setting up glyph data in gfxTextRuns.
796 * A generic, platform-independent shaper relies only on the standard
797 * gfxFont interface and can work with any concrete subclass of gfxFont.
799 * Platform-specific implementations designed to interface to platform
800 * shaping APIs such as Uniscribe or CoreText may rely on features of a
801 * specific font subclass to access native font references
802 * (such as CTFont, HFONT, DWriteFont, etc).
805 class gfxFontShaper
{
807 gfxFontShaper(gfxFont
*aFont
)
810 NS_ASSERTION(aFont
, "shaper requires a valid font!");
813 virtual ~gfxFontShaper() { }
815 virtual PRBool
InitTextRun(gfxContext
*aContext
,
816 gfxTextRun
*aTextRun
,
817 const PRUnichar
*aString
,
820 PRInt32 aRunScript
) = 0;
822 gfxFont
*GetFont() const { return mFont
; }
825 // the font this shaper is working with
829 /* a SPECIFIC single font family */
830 class THEBES_API gfxFont
{
832 nsrefcnt
AddRef(void) {
833 NS_PRECONDITION(PRInt32(mRefCnt
) >= 0, "illegal refcnt");
834 if (mExpirationState
.IsTracked()) {
835 gfxFontCache::GetCache()->RemoveObject(this);
838 NS_LOG_ADDREF(this, mRefCnt
, "gfxFont", sizeof(*this));
841 nsrefcnt
Release(void) {
842 NS_PRECONDITION(0 != mRefCnt
, "dup release");
844 NS_LOG_RELEASE(this, mRefCnt
, "gfxFont");
847 // |this| may have been deleted.
853 PRInt32
GetRefCount() { return mRefCnt
; }
855 // options to specify the kind of AA to be used when creating a font
864 nsAutoRefCnt mRefCnt
;
866 void NotifyReleased() {
867 gfxFontCache
*cache
= gfxFontCache::GetCache();
869 // Don't delete just yet; return the object to the cache for
870 // possibly recycling within some time limit
871 cache
->NotifyReleased(this);
873 // The cache may have already been shut down.
878 gfxFont(gfxFontEntry
*aFontEntry
, const gfxFontStyle
*aFontStyle
,
879 AntialiasOption anAAOption
= kAntialiasDefault
);
884 PRBool
Valid() const {
888 // options for the kind of bounding box to return from measurement
891 // A box that encloses all the painted pixels, and may
892 // include sidebearings and/or additional ascent/descent
893 // within the glyph cell even if the ink is smaller.
895 // A box that tightly encloses all the painted pixels
896 // (although actually on Windows, at least, it may be
897 // slightly larger than strictly necessary because
898 // we can't get precise extents with ClearType).
899 TIGHT_HINTED_OUTLINE_EXTENTS
900 // A box that tightly encloses the glyph outline,
901 // ignoring possible antialiasing pixels that extend
903 // NOTE: The default implementation of gfxFont::Measure(),
904 // which works with the glyph extents cache, does not
905 // differentiate between this and TIGHT_INK_EXTENTS.
906 // Whether the distinction is important depends on the
907 // antialiasing behavior of the platform; currently the
908 // distinction is only implemented in the gfxWindowsFont
909 // subclass, because of ClearType's tendency to paint
910 // outside the hinted outline.
911 // Also NOTE: it is relatively expensive to request this,
912 // as it does not use cached glyph extents in the font.
915 const nsString
& GetName() const { return mFontEntry
->Name(); }
916 const gfxFontStyle
*GetStyle() const { return &mStyle
; }
918 virtual nsString
GetUniqueName() { return GetName(); }
920 virtual gfxFont
* CopyWithAntialiasOption(AntialiasOption anAAOption
) {
921 // platforms where this actually matters should override
925 gfxFloat
GetAdjustedSize() const {
926 return mAdjustedSize
> 0.0 ? mAdjustedSize
: mStyle
.size
;
929 float FUnitsToDevUnitsFactor() const {
930 // check this was set up during font initialization
931 NS_ASSERTION(mFUnitsConvFactor
> 0.0f
, "mFUnitsConvFactor not valid");
932 return mFUnitsConvFactor
;
935 // check whether this is an sfnt we can potentially use with harfbuzz
936 PRBool
FontCanSupportHarfBuzz() {
937 return mFontEntry
->HasCmapTable();
940 // Access to raw font table data (needed for Harfbuzz):
941 // returns a pointer to data owned by the fontEntry or the OS,
942 // which will remain valid until released.
944 // Default implementations forward to the font entry, which
945 // maintains a shared table cache; however, subclasses may
946 // override if they can provide more efficient table access.
948 // Get pointer to a specific font table, or an empty blob if
949 // the table doesn't exist in the font
950 virtual hb_blob_t
*GetFontTable(PRUint32 aTag
) {
951 return mFontEntry
->GetFontTable(aTag
);
954 // subclasses may provide hinted glyph widths (in font units);
955 // if they do not override this, harfbuzz will use unhinted widths
956 // derived from the font tables
957 virtual PRBool
ProvidesHintedWidths() const {
961 virtual PRInt32
GetHintedGlyphWidth(gfxContext
*aCtx
, PRUint16 aGID
) {
968 gfxFloat superscriptOffset
;
969 gfxFloat subscriptOffset
;
970 gfxFloat strikeoutSize
;
971 gfxFloat strikeoutOffset
;
972 gfxFloat underlineSize
;
973 gfxFloat underlineOffset
;
975 gfxFloat internalLeading
;
976 gfxFloat externalLeading
;
986 gfxFloat aveCharWidth
;
988 gfxFloat zeroOrAveCharWidth
; // width of '0', or if there is
989 // no '0' glyph in this font,
990 // equal to .aveCharWidth
992 virtual const gfxFont::Metrics
& GetMetrics() = 0;
995 * We let layout specify spacing on either side of any
996 * character. We need to specify both before and after
997 * spacing so that substring measurement can do the right things.
998 * These values are in appunits. They're always an integral number of
999 * appunits, but we specify them in floats in case very large spacing
1000 * values are required.
1007 * Metrics for a particular string
1009 struct THEBES_API RunMetrics
{
1011 mAdvanceWidth
= mAscent
= mDescent
= 0.0;
1012 mBoundingBox
= gfxRect(0,0,0,0);
1015 void CombineWith(const RunMetrics
& aOther
, PRBool aOtherIsOnLeft
);
1017 // can be negative (partly due to negative spacing).
1018 // Advance widths should be additive: the advance width of the
1019 // (offset1, length1) plus the advance width of (offset1 + length1,
1020 // length2) should be the advance width of (offset1, length1 + length2)
1021 gfxFloat mAdvanceWidth
;
1023 // For zero-width substrings, these must be zero!
1024 gfxFloat mAscent
; // always non-negative
1025 gfxFloat mDescent
; // always non-negative
1027 // Bounding box that is guaranteed to include everything drawn.
1028 // If a tight boundingBox was requested when these metrics were
1029 // generated, this will tightly wrap the glyphs, otherwise it is
1030 // "loose" and may be larger than the true bounding box.
1031 // Coordinates are relative to the baseline left origin, so typically
1032 // mBoundingBox.y == -mAscent
1033 gfxRect mBoundingBox
;
1037 * Draw a series of glyphs to aContext. The direction of aTextRun must
1039 * @param aStart the first character to draw
1040 * @param aEnd draw characters up to here
1041 * @param aBaselineOrigin the baseline origin; the left end of the baseline
1042 * for LTR textruns, the right end of the baseline for RTL textruns. On return,
1043 * this should be updated to the other end of the baseline. In application
1045 * @param aSpacing spacing to insert before and after characters (for RTL
1046 * glyphs, before-spacing is inserted to the right of characters). There
1047 * are aEnd - aStart elements in this array, unless it's null to indicate
1048 * that there is no spacing.
1049 * @param aDrawToPath when true, add the glyph outlines to the current path
1050 * instead of drawing the glyphs
1052 * Callers guarantee:
1053 * -- aStart and aEnd are aligned to cluster and ligature boundaries
1054 * -- all glyphs use this font
1056 * The default implementation builds a cairo glyph array and
1057 * calls cairo_show_glyphs or cairo_glyph_path.
1059 virtual void Draw(gfxTextRun
*aTextRun
, PRUint32 aStart
, PRUint32 aEnd
,
1060 gfxContext
*aContext
, PRBool aDrawToPath
, gfxPoint
*aBaselineOrigin
,
1063 * Measure a run of characters. See gfxTextRun::Metrics.
1064 * @param aTight if false, then return the union of the glyph extents
1065 * with the font-box for the characters (the rectangle with x=0,width=
1066 * the advance width for the character run,y=-(font ascent), and height=
1067 * font ascent + font descent). Otherwise, we must return as tight as possible
1068 * an approximation to the area actually painted by glyphs.
1069 * @param aContextForTightBoundingBox when aTight is true, this must
1071 * @param aSpacing spacing to insert before and after glyphs. The bounding box
1072 * need not include the spacing itself, but the spacing affects the glyph
1073 * positions. null if there is no spacing.
1075 * Callers guarantee:
1076 * -- aStart and aEnd are aligned to cluster and ligature boundaries
1077 * -- all glyphs use this font
1079 * The default implementation just uses font metrics and aTextRun's
1080 * advances, and assumes no characters fall outside the font box. In
1081 * general this is insufficient, because that assumption is not always true.
1083 virtual RunMetrics
Measure(gfxTextRun
*aTextRun
,
1084 PRUint32 aStart
, PRUint32 aEnd
,
1085 BoundingBoxType aBoundingBoxType
,
1086 gfxContext
*aContextForTightBoundingBox
,
1089 * Line breaks have been changed at the beginning and/or end of a substring
1090 * of the text. Reshaping may be required; glyph updating is permitted.
1091 * @return true if anything was changed, false otherwise
1093 PRBool
NotifyLineBreaksChanged(gfxTextRun
*aTextRun
,
1094 PRUint32 aStart
, PRUint32 aLength
)
1095 { return PR_FALSE
; }
1097 // Expiration tracking
1098 nsExpirationState
*GetExpirationState() { return &mExpirationState
; }
1100 // Get the glyphID of a space
1101 virtual PRUint32
GetSpaceGlyph() = 0;
1103 gfxGlyphExtents
*GetOrCreateGlyphExtents(PRUint32 aAppUnitsPerDevUnit
);
1105 // You need to call SetupCairoFont on the aCR just before calling this
1106 virtual void SetupGlyphExtents(gfxContext
*aContext
, PRUint32 aGlyphID
,
1107 PRBool aNeedTight
, gfxGlyphExtents
*aExtents
);
1109 // This is called by the default Draw() implementation above.
1110 virtual PRBool
SetupCairoFont(gfxContext
*aContext
) = 0;
1112 PRBool
IsSyntheticBold() { return mSyntheticBoldOffset
!= 0; }
1113 PRUint32
GetSyntheticBoldOffset() { return mSyntheticBoldOffset
; }
1115 gfxFontEntry
*GetFontEntry() { return mFontEntry
.get(); }
1116 PRBool
HasCharacter(PRUint32 ch
) {
1119 return mFontEntry
->HasCharacter(ch
);
1122 PRUint16
GetUVSGlyph(PRUint32 aCh
, PRUint32 aVS
) {
1126 return mFontEntry
->GetUVSGlyph(aCh
, aVS
);
1129 // Default simply calls m[Platform|HarfBuzz]Shaper->InitTextRun().
1130 // Override if the font class wants to give special handling
1131 // to shaper failure.
1132 // Returns PR_FALSE if shaping failed (though currently we
1133 // don't have any good way to handle that situation).
1134 virtual PRBool
InitTextRun(gfxContext
*aContext
,
1135 gfxTextRun
*aTextRun
,
1136 const PRUnichar
*aString
,
1138 PRUint32 aRunLength
,
1139 PRInt32 aRunScript
);
1142 nsRefPtr
<gfxFontEntry
> mFontEntry
;
1144 PRPackedBool mIsValid
;
1145 nsExpirationState mExpirationState
;
1146 gfxFontStyle mStyle
;
1147 nsAutoTArray
<gfxGlyphExtents
*,1> mGlyphExtentsArray
;
1149 gfxFloat mAdjustedSize
;
1151 float mFUnitsConvFactor
; // conversion factor from font units to dev units
1153 // synthetic bolding for environments where this is not supported by the platform
1154 PRUint32 mSyntheticBoldOffset
; // number of devunit pixels to offset double-strike, 0 ==> no bolding
1156 // the AA setting requested for this font - may affect glyph bounds
1157 AntialiasOption mAntialiasOption
;
1159 // a copy of the font without antialiasing, if needed for separate
1160 // measurement by mathml code
1161 nsAutoPtr
<gfxFont
> mNonAAFont
;
1163 // we may switch between these shapers on the fly, based on the script
1164 // of the text run being shaped
1165 nsAutoPtr
<gfxFontShaper
> mPlatformShaper
;
1166 nsAutoPtr
<gfxFontShaper
> mHarfBuzzShaper
;
1168 // Create a default platform text shaper for this font.
1169 // (TODO: This should become pure virtual once all font backends have
1171 virtual void CreatePlatformShaper() { }
1173 // Helper for subclasses that want to initialize standard metrics from the
1174 // tables of sfnt (TrueType/OpenType) fonts.
1175 // This will use mFUnitsConvFactor if it is already set, else compute it
1176 // from mAdjustedSize and the unitsPerEm in the font's 'head' table.
1177 // Returns TRUE and sets mIsValid=TRUE if successful;
1178 // Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
1179 // Returns FALSE if the font does not appear to be an sfnt at all,
1180 // and should be handled (if possible) using other APIs.
1181 PRBool
InitMetricsFromSfntTables(Metrics
& aMetrics
);
1183 // Helper to calculate various derived metrics from the results of
1184 // InitMetricsFromSfntTables or equivalent platform code
1185 void CalculateDerivedMetrics(Metrics
& aMetrics
);
1187 // some fonts have bad metrics, this method sanitize them.
1188 // if this font has bad underline offset, aIsBadUnderlineFont should be true.
1189 void SanitizeMetrics(gfxFont::Metrics
*aMetrics
, PRBool aIsBadUnderlineFont
);
1192 // proportion of ascent used for x-height, if unable to read value from font
1193 #define DEFAULT_XHEIGHT_FACTOR 0.56f
1195 class THEBES_API gfxTextRunFactory
{
1196 NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory
)
1199 // Flags in the mask 0xFFFF0000 are reserved for textrun clients
1200 // Flags in the mask 0x0000F000 are reserved for per-platform fonts
1201 // Flags in the mask 0x00000FFF are set by the textrun creator.
1203 CACHE_TEXT_FLAGS
= 0xF0000000,
1204 USER_TEXT_FLAGS
= 0x0FFF0000,
1205 PLATFORM_TEXT_FLAGS
= 0x0000F000,
1206 TEXTRUN_TEXT_FLAGS
= 0x00000FFF,
1207 SETTABLE_FLAGS
= CACHE_TEXT_FLAGS
| USER_TEXT_FLAGS
,
1210 * When set, the text string pointer used to create the text run
1211 * is guaranteed to be available during the lifetime of the text run.
1213 TEXT_IS_PERSISTENT
= 0x0001,
1215 * When set, the text is known to be all-ASCII (< 128).
1217 TEXT_IS_ASCII
= 0x0002,
1219 * When set, the text is RTL.
1221 TEXT_IS_RTL
= 0x0004,
1223 * When set, spacing is enabled and the textrun needs to call GetSpacing
1224 * on the spacing provider.
1226 TEXT_ENABLE_SPACING
= 0x0008,
1228 * When set, GetHyphenationBreaks may return true for some character
1229 * positions, otherwise it will always return false for all characters.
1231 TEXT_ENABLE_HYPHEN_BREAKS
= 0x0010,
1233 * When set, the text has no characters above 255 and it is stored
1234 * in the textrun in 8-bit format.
1236 TEXT_IS_8BIT
= 0x0020,
1238 * When set, the RunMetrics::mBoundingBox field will be initialized
1239 * properly based on glyph extents, in particular, glyph extents that
1240 * overflow the standard font-box (the box defined by the ascent, descent
1241 * and advance width of the glyph). When not set, it may just be the
1242 * standard font-box even if glyphs overflow.
1244 TEXT_NEED_BOUNDING_BOX
= 0x0040,
1246 * When set, optional ligatures are disabled. Ligatures that are
1247 * required for legible text should still be enabled.
1249 TEXT_DISABLE_OPTIONAL_LIGATURES
= 0x0080,
1251 * When set, the textrun should favour speed of construction over
1252 * quality. This may involve disabling ligatures and/or kerning or
1255 TEXT_OPTIMIZE_SPEED
= 0x0100
1259 * This record contains all the parameters needed to initialize a textrun.
1262 // A reference context suggesting where the textrun will be rendered
1263 gfxContext
*mContext
;
1264 // Pointer to arbitrary user data (which should outlive the textrun)
1266 // A description of which characters have been stripped from the original
1267 // DOM string to produce the characters in the textrun. May be null
1268 // if that information is not relevant.
1269 gfxSkipChars
*mSkipChars
;
1270 // A list of where linebreaks are currently placed in the textrun. May
1271 // be null if mInitialBreakCount is zero.
1272 PRUint32
*mInitialBreaks
;
1273 PRUint32 mInitialBreakCount
;
1274 // The ratio to use to convert device pixels to application layout units
1275 PRUint32 mAppUnitsPerDevUnit
;
1278 virtual ~gfxTextRunFactory() {}
1282 * gfxTextRun is an abstraction for drawing and measuring substrings of a run
1283 * of text. It stores runs of positioned glyph data, each run having a single
1284 * gfxFont. The glyphs are associated with a string of source text, and the
1285 * gfxTextRun APIs take parameters that are offsets into that source text.
1287 * gfxTextRuns are not refcounted. They should be deleted when no longer required.
1289 * gfxTextRuns are mostly immutable. The only things that can change are
1290 * inter-cluster spacing and line break placement. Spacing is always obtained
1291 * lazily by methods that need it, it is not cached. Line breaks are stored
1292 * persistently (insofar as they affect the shaping of glyphs; gfxTextRun does
1293 * not actually do anything to explicitly account for line breaks). Initially
1294 * there are no line breaks. The textrun can record line breaks before or after
1295 * any given cluster. (Line breaks specified inside clusters are ignored.)
1297 * It is important that zero-length substrings are handled correctly. This will
1300 * gfxTextRun stores a list of zero or more glyphs for each character. For each
1301 * glyph we store the glyph ID, the advance, and possibly an xoffset and yoffset.
1302 * The idea is that a string is rendered by a loop that draws each glyph
1303 * at its designated offset from the current point, then advances the current
1304 * point by the glyph's advance in the direction of the textrun (LTR or RTL).
1305 * Each glyph advance is always rounded to the nearest appunit; this ensures
1306 * consistent results when dividing the text in a textrun into multiple text
1307 * frames (frame boundaries are always aligned to appunits). We optimize
1308 * for the case where a character has a single glyph and zero xoffset and yoffset,
1309 * and the glyph ID and advance are in a reasonable range so we can pack all
1310 * necessary data into 32 bits.
1312 * gfxTextRun methods that measure or draw substrings will associate all the
1313 * glyphs in a cluster with the first character of the cluster; if that character
1314 * is in the substring, the glyphs will be measured or drawn, otherwise they
1317 class THEBES_API gfxTextRun
{
1319 virtual ~gfxTextRun();
1321 typedef gfxFont::RunMetrics Metrics
;
1323 // Public textrun API for general use
1325 PRBool
IsClusterStart(PRUint32 aPos
) {
1326 NS_ASSERTION(0 <= aPos
&& aPos
< mCharacterCount
, "aPos out of range");
1327 return mCharacterGlyphs
[aPos
].IsClusterStart();
1329 PRBool
IsLigatureGroupStart(PRUint32 aPos
) {
1330 NS_ASSERTION(0 <= aPos
&& aPos
< mCharacterCount
, "aPos out of range");
1331 return mCharacterGlyphs
[aPos
].IsLigatureGroupStart();
1333 PRBool
CanBreakLineBefore(PRUint32 aPos
) {
1334 NS_ASSERTION(0 <= aPos
&& aPos
< mCharacterCount
, "aPos out of range");
1335 return mCharacterGlyphs
[aPos
].CanBreakBefore();
1338 PRUint32
GetLength() { return mCharacterCount
; }
1340 // All PRUint32 aStart, PRUint32 aLength ranges below are restricted to
1341 // grapheme cluster boundaries! All offsets are in terms of the string
1342 // passed into MakeTextRun.
1344 // All coordinates are in layout/app units
1347 * Set the potential linebreaks for a substring of the textrun. These are
1348 * the "allow break before" points. Initially, there are no potential
1351 * This can change glyphs and/or geometry! Some textruns' shapes
1352 * depend on potential line breaks (e.g., title-case-converting textruns).
1353 * This function is virtual so that those textruns can reshape themselves.
1355 * @return true if this changed the linebreaks, false if the new line
1356 * breaks are the same as the old
1358 virtual PRBool
SetPotentialLineBreaks(PRUint32 aStart
, PRUint32 aLength
,
1359 PRPackedBool
*aBreakBefore
,
1360 gfxContext
*aRefContext
);
1363 * Layout provides PropertyProvider objects. These allow detection of
1364 * potential line break points and computation of spacing. We pass the data
1365 * this way to allow lazy data acquisition; for example BreakAndMeasureText
1366 * will want to only ask for properties of text it's actually looking at.
1368 * NOTE that requested spacing may not actually be applied, if the textrun
1369 * is unable to apply it in some context. Exception: spacing around a
1370 * whitespace character MUST always be applied.
1372 class PropertyProvider
{
1374 // Detect hyphenation break opportunities in the given range; breaks
1375 // not at cluster boundaries will be ignored.
1376 virtual void GetHyphenationBreaks(PRUint32 aStart
, PRUint32 aLength
,
1377 PRPackedBool
*aBreakBefore
) = 0;
1379 // Returns the extra width that will be consumed by a hyphen. This should
1380 // be constant for a given textrun.
1381 virtual gfxFloat
GetHyphenWidth() = 0;
1383 typedef gfxFont::Spacing Spacing
;
1386 * Get the spacing around the indicated characters. Spacing must be zero
1387 * inside clusters. In other words, if character i is not
1388 * CLUSTER_START, then character i-1 must have zero after-spacing and
1389 * character i must have zero before-spacing.
1391 virtual void GetSpacing(PRUint32 aStart
, PRUint32 aLength
,
1392 Spacing
*aSpacing
) = 0;
1396 * Draws a substring. Uses only GetSpacing from aBreakProvider.
1397 * The provided point is the baseline origin on the left of the string
1398 * for LTR, on the right of the string for RTL.
1399 * @param aDirtyRect if non-null, drawing outside of the rectangle can be
1400 * (but does not need to be) dropped. Note that if this is null, we cannot
1401 * draw partial ligatures and we will assert if partial ligatures
1403 * @param aAdvanceWidth if non-null, the advance width of the substring
1406 * Drawing should respect advance widths in the sense that for LTR runs,
1407 * Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by
1408 * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1 + length1, length2,
1409 * dirty, &provider, nsnull) should have the same effect as
1410 * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
1411 * For RTL runs the rule is:
1412 * Draw(ctx, pt, offset1 + length1, length2, dirty, &provider, &advance) followed by
1413 * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1, length1,
1414 * dirty, &provider, nsnull) should have the same effect as
1415 * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
1417 * Glyphs should be drawn in logical content order, which can be significant
1418 * if they overlap (perhaps due to negative spacing).
1420 void Draw(gfxContext
*aContext
, gfxPoint aPt
,
1421 PRUint32 aStart
, PRUint32 aLength
,
1422 const gfxRect
*aDirtyRect
,
1423 PropertyProvider
*aProvider
,
1424 gfxFloat
*aAdvanceWidth
);
1427 * Renders a substring to a path. Uses only GetSpacing from aBreakProvider.
1428 * The provided point is the baseline origin on the left of the string
1429 * for LTR, on the right of the string for RTL.
1430 * @param aAdvanceWidth if non-null, the advance width of the substring
1433 * Drawing should respect advance widths in the way that Draw above does.
1435 * Glyphs should be drawn in logical content order.
1437 * UNLIKE Draw above, this cannot be used to render substrings that start or
1438 * end inside a ligature.
1440 void DrawToPath(gfxContext
*aContext
, gfxPoint aPt
,
1441 PRUint32 aStart
, PRUint32 aLength
,
1442 PropertyProvider
*aBreakProvider
,
1443 gfxFloat
*aAdvanceWidth
);
1446 * Computes the ReflowMetrics for a substring.
1447 * Uses GetSpacing from aBreakProvider.
1448 * @param aBoundingBoxType which kind of bounding box (loose/tight)
1450 Metrics
MeasureText(PRUint32 aStart
, PRUint32 aLength
,
1451 gfxFont::BoundingBoxType aBoundingBoxType
,
1452 gfxContext
*aRefContextForTightBoundingBox
,
1453 PropertyProvider
*aProvider
);
1456 * Computes just the advance width for a substring.
1457 * Uses GetSpacing from aBreakProvider.
1459 gfxFloat
GetAdvanceWidth(PRUint32 aStart
, PRUint32 aLength
,
1460 PropertyProvider
*aProvider
);
1463 * Clear all stored line breaks for the given range (both before and after),
1464 * and then set the line-break state before aStart to aBreakBefore and
1465 * after the last cluster to aBreakAfter.
1467 * We require that before and after line breaks be consistent. For clusters
1468 * i and i+1, we require that if there is a break after cluster i, a break
1469 * will be specified before cluster i+1. This may be temporarily violated
1470 * (e.g. after reflowing line L and before reflowing line L+1); to handle
1471 * these temporary violations, we say that there is a break betwen i and i+1
1472 * if a break is specified after i OR a break is specified before i+1.
1474 * This can change textrun geometry! The existence of a linebreak can affect
1475 * the advance width of the cluster before the break (when kerning) or the
1476 * geometry of one cluster before the break or any number of clusters
1477 * after the break. (The one-cluster-before-the-break limit is somewhat
1478 * arbitrary; if some scripts require breaking it, then we need to
1479 * alter nsTextFrame::TrimTrailingWhitespace, perhaps drastically becase
1480 * it could affect the layout of frames before it...)
1482 * We return true if glyphs or geometry changed, false otherwise. This
1483 * function is virtual so that gfxTextRun subclasses can reshape
1486 * @param aAdvanceWidthDelta if non-null, returns the change in advance
1487 * width of the given range.
1489 virtual PRBool
SetLineBreaks(PRUint32 aStart
, PRUint32 aLength
,
1490 PRBool aLineBreakBefore
, PRBool aLineBreakAfter
,
1491 gfxFloat
*aAdvanceWidthDelta
,
1492 gfxContext
*aRefContext
);
1495 * Finds the longest substring that will fit into the given width.
1496 * Uses GetHyphenationBreaks and GetSpacing from aBreakProvider.
1497 * Guarantees the following:
1498 * -- 0 <= result <= aMaxLength
1499 * -- result is the maximal value of N such that either
1500 * N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
1501 * OR N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
1502 * OR N == aMaxLength && GetAdvanceWidth(aStart, N) <= aWidth
1503 * where GetAdvanceWidth assumes the effect of
1504 * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
1505 * -- if no such N exists, then result is the smallest N such that
1506 * N < aMaxLength && line break at N
1507 * OR N < aMaxLength && hyphen break at N
1508 * OR N == aMaxLength
1510 * The call has the effect of
1511 * SetLineBreaks(aStart, result, aLineBreakBefore, result < aMaxLength, aProvider)
1512 * and the returned metrics and the invariants above reflect this.
1514 * @param aMaxLength this can be PR_UINT32_MAX, in which case the length used
1515 * is up to the end of the string
1516 * @param aLineBreakBefore set to true if and only if there is an actual
1517 * line break at the start of this string.
1518 * @param aSuppressInitialBreak if true, then we assume there is no possible
1519 * linebreak before aStart. If false, then we will check the internal
1520 * line break opportunity state before deciding whether to return 0 as the
1521 * character to break before.
1522 * @param aTrimWhitespace if non-null, then we allow a trailing run of
1523 * spaces to be trimmed; the width of the space(s) will not be included in
1524 * the measured string width for comparison with the limit aWidth, and
1525 * trimmed spaces will not be included in returned metrics. The width
1526 * of the trimmed spaces will be returned in aTrimWhitespace.
1527 * Trimmed spaces are still counted in the "characters fit" result.
1528 * @param aMetrics if non-null, we fill this in for the returned substring.
1529 * If a hyphenation break was used, the hyphen is NOT included in the returned metrics.
1530 * @param aBoundingBoxType whether to make the bounding box in aMetrics tight
1531 * @param aRefContextForTightBoundingBox a reference context to get the
1532 * tight bounding box, if requested
1533 * @param aUsedHyphenation if non-null, records if we selected a hyphenation break
1534 * @param aLastBreak if non-null and result is aMaxLength, we set this to
1535 * the maximal N such that
1536 * N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
1537 * OR N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
1538 * or PR_UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
1540 * SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
1542 * @param aCanWordWrap true if we can break between any two grapheme
1543 * clusters. This is set by word-wrap: break-word
1545 * @param aBreakPriority in/out the priority of the break opportunity
1546 * saved in the line. If we are prioritizing break opportunities, we will
1547 * not set a break with a lower priority. @see gfxBreakPriority.
1549 * Note that negative advance widths are possible especially if negative
1550 * spacing is provided.
1552 PRUint32
BreakAndMeasureText(PRUint32 aStart
, PRUint32 aMaxLength
,
1553 PRBool aLineBreakBefore
, gfxFloat aWidth
,
1554 PropertyProvider
*aProvider
,
1555 PRBool aSuppressInitialBreak
,
1556 gfxFloat
*aTrimWhitespace
,
1558 gfxFont::BoundingBoxType aBoundingBoxType
,
1559 gfxContext
*aRefContextForTightBoundingBox
,
1560 PRBool
*aUsedHyphenation
,
1561 PRUint32
*aLastBreak
,
1562 PRBool aCanWordWrap
,
1563 gfxBreakPriority
*aBreakPriority
);
1566 * Update the reference context.
1567 * XXX this is a hack. New text frame does not call this. Use only
1568 * temporarily for old text frame.
1570 void SetContext(gfxContext
*aContext
) {}
1574 PRBool
IsRightToLeft() const { return (mFlags
& gfxTextRunFactory::TEXT_IS_RTL
) != 0; }
1575 gfxFloat
GetDirection() const { return (mFlags
& gfxTextRunFactory::TEXT_IS_RTL
) ? -1.0 : 1.0; }
1576 void *GetUserData() const { return mUserData
; }
1577 void SetUserData(void *aUserData
) { mUserData
= aUserData
; }
1578 PRUint32
GetFlags() const { return mFlags
; }
1579 void SetFlagBits(PRUint32 aFlags
) {
1580 NS_ASSERTION(!(aFlags
& ~gfxTextRunFactory::SETTABLE_FLAGS
),
1581 "Only user flags should be mutable");
1584 void ClearFlagBits(PRUint32 aFlags
) {
1585 NS_ASSERTION(!(aFlags
& ~gfxTextRunFactory::SETTABLE_FLAGS
),
1586 "Only user flags should be mutable");
1589 const gfxSkipChars
& GetSkipChars() const { return mSkipChars
; }
1590 PRUint32
GetAppUnitsPerDevUnit() const { return mAppUnitsPerDevUnit
; }
1591 gfxFontGroup
*GetFontGroup() const { return mFontGroup
; }
1592 const PRUint8
*GetText8Bit() const
1593 { return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
) ? mText
.mSingle
: nsnull
; }
1594 const PRUnichar
*GetTextUnicode() const
1595 { return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
) ? nsnull
: mText
.mDouble
; }
1596 const void *GetTextAt(PRUint32 aIndex
) {
1597 return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
)
1598 ? static_cast<const void *>(mText
.mSingle
+ aIndex
)
1599 : static_cast<const void *>(mText
.mDouble
+ aIndex
);
1601 const PRUnichar
GetChar(PRUint32 i
) const
1602 { return (mFlags
& gfxTextRunFactory::TEXT_IS_8BIT
) ? mText
.mSingle
[i
] : mText
.mDouble
[i
]; }
1603 PRUint32
GetHashCode() const { return mHashCode
; }
1604 void SetHashCode(PRUint32 aHash
) { mHashCode
= aHash
; }
1606 // Call this, don't call "new gfxTextRun" directly. This does custom
1607 // allocation and initialization
1608 static gfxTextRun
*Create(const gfxTextRunFactory::Parameters
*aParams
,
1609 const void *aText
, PRUint32 aLength
, gfxFontGroup
*aFontGroup
, PRUint32 aFlags
);
1611 // Clone this textrun, according to the given parameters. This textrun's
1612 // glyph data is copied, so the text and length must be the same as this
1613 // textrun's. If there's a problem, return null. Actual linebreaks will
1614 // be set as per aParams; there will be no potential linebreaks.
1615 // If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
1616 // textrun will copy it.
1617 virtual gfxTextRun
*Clone(const gfxTextRunFactory::Parameters
*aParams
, const void *aText
,
1618 PRUint32 aLength
, gfxFontGroup
*aFontGroup
, PRUint32 aFlags
);
1621 * This class records the information associated with a character in the
1622 * input string. It's optimized for the case where there is one glyph
1623 * representing that character alone.
1625 * A character can have zero or more associated glyphs. Each glyph
1626 * has an advance width and an x and y offset.
1627 * A character may be the start of a cluster.
1628 * A character may be the start of a ligature group.
1629 * A character can be "missing", indicating that the system is unable
1630 * to render the character.
1632 * All characters in a ligature group conceptually share all the glyphs
1633 * associated with the characters in a group.
1635 class CompressedGlyph
{
1637 CompressedGlyph() { mValue
= 0; }
1640 // Indicates that a cluster and ligature group starts at this
1641 // character; this character has a single glyph with a reasonable
1642 // advance and zero offsets. A "reasonable" advance
1643 // is one that fits in the available bits (currently 14) (specified
1645 FLAG_IS_SIMPLE_GLYPH
= 0x80000000U
,
1646 // Indicates that a linebreak is allowed before this character
1647 FLAG_CAN_BREAK_BEFORE
= 0x40000000U
,
1649 // The advance is stored in appunits
1650 ADVANCE_MASK
= 0x3FFF0000U
,
1653 GLYPH_MASK
= 0x0000FFFFU
,
1655 // Non-simple glyphs may or may not have glyph data in the
1656 // corresponding mDetailedGlyphs entry. They have the following
1659 // When NOT set, indicates that this character corresponds to a
1660 // missing glyph and should be skipped (or possibly, render the character
1661 // Unicode value in some special way). If there are glyphs,
1662 // the mGlyphID is actually the UTF16 character code. The bit is
1663 // inverted so we can memset the array to zero to indicate all missing.
1664 FLAG_NOT_MISSING
= 0x01,
1665 FLAG_NOT_CLUSTER_START
= 0x02,
1666 FLAG_NOT_LIGATURE_GROUP_START
= 0x04,
1668 GLYPH_COUNT_MASK
= 0x00FFFF00U
,
1669 GLYPH_COUNT_SHIFT
= 8
1672 // "Simple glyphs" have a simple glyph ID, simple advance and their
1673 // x and y offsets are zero. Also the glyph extents do not overflow
1674 // the font-box defined by the font ascent, descent and glyph advance width.
1675 // These case is optimized to avoid storing DetailedGlyphs.
1677 // Returns true if the glyph ID aGlyph fits into the compressed representation
1678 static PRBool
IsSimpleGlyphID(PRUint32 aGlyph
) {
1679 return (aGlyph
& GLYPH_MASK
) == aGlyph
;
1681 // Returns true if the advance aAdvance fits into the compressed representation.
1682 // aAdvance is in appunits.
1683 static PRBool
IsSimpleAdvance(PRUint32 aAdvance
) {
1684 return (aAdvance
& (ADVANCE_MASK
>> ADVANCE_SHIFT
)) == aAdvance
;
1687 PRBool
IsSimpleGlyph() const { return (mValue
& FLAG_IS_SIMPLE_GLYPH
) != 0; }
1688 PRUint32
GetSimpleAdvance() const { return (mValue
& ADVANCE_MASK
) >> ADVANCE_SHIFT
; }
1689 PRUint32
GetSimpleGlyph() const { return mValue
& GLYPH_MASK
; }
1691 PRBool
IsMissing() const { return (mValue
& (FLAG_NOT_MISSING
|FLAG_IS_SIMPLE_GLYPH
)) == 0; }
1692 PRBool
IsClusterStart() const {
1693 return (mValue
& FLAG_IS_SIMPLE_GLYPH
) || !(mValue
& FLAG_NOT_CLUSTER_START
);
1695 PRBool
IsLigatureGroupStart() const {
1696 return (mValue
& FLAG_IS_SIMPLE_GLYPH
) || !(mValue
& FLAG_NOT_LIGATURE_GROUP_START
);
1698 PRBool
IsLigatureContinuation() const {
1699 return (mValue
& FLAG_IS_SIMPLE_GLYPH
) == 0 &&
1700 (mValue
& (FLAG_NOT_LIGATURE_GROUP_START
| FLAG_NOT_MISSING
)) ==
1701 (FLAG_NOT_LIGATURE_GROUP_START
| FLAG_NOT_MISSING
);
1704 PRBool
CanBreakBefore() const { return (mValue
& FLAG_CAN_BREAK_BEFORE
) != 0; }
1705 // Returns FLAG_CAN_BREAK_BEFORE if the setting changed, 0 otherwise
1706 PRUint32
SetCanBreakBefore(PRBool aCanBreakBefore
) {
1707 NS_ASSERTION(aCanBreakBefore
== PR_FALSE
|| aCanBreakBefore
== PR_TRUE
,
1708 "Bogus break-before value!");
1709 PRUint32 breakMask
= aCanBreakBefore
*FLAG_CAN_BREAK_BEFORE
;
1710 PRUint32 toggle
= breakMask
^ (mValue
& FLAG_CAN_BREAK_BEFORE
);
1715 CompressedGlyph
& SetSimpleGlyph(PRUint32 aAdvanceAppUnits
, PRUint32 aGlyph
) {
1716 NS_ASSERTION(IsSimpleAdvance(aAdvanceAppUnits
), "Advance overflow");
1717 NS_ASSERTION(IsSimpleGlyphID(aGlyph
), "Glyph overflow");
1718 mValue
= (mValue
& FLAG_CAN_BREAK_BEFORE
) | FLAG_IS_SIMPLE_GLYPH
|
1719 (aAdvanceAppUnits
<< ADVANCE_SHIFT
) | aGlyph
;
1722 CompressedGlyph
& SetComplex(PRBool aClusterStart
, PRBool aLigatureStart
,
1723 PRUint32 aGlyphCount
) {
1724 mValue
= (mValue
& FLAG_CAN_BREAK_BEFORE
) | FLAG_NOT_MISSING
|
1725 (aClusterStart
? 0 : FLAG_NOT_CLUSTER_START
) |
1726 (aLigatureStart
? 0 : FLAG_NOT_LIGATURE_GROUP_START
) |
1727 (aGlyphCount
<< GLYPH_COUNT_SHIFT
);
1731 * Missing glyphs are treated as cluster and ligature group starts.
1733 CompressedGlyph
& SetMissing(PRUint32 aGlyphCount
) {
1734 mValue
= (mValue
& FLAG_CAN_BREAK_BEFORE
) |
1735 (aGlyphCount
<< GLYPH_COUNT_SHIFT
);
1738 PRUint32
GetGlyphCount() const {
1739 NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
1740 return (mValue
& GLYPH_COUNT_MASK
) >> GLYPH_COUNT_SHIFT
;
1748 * When the glyphs for a character don't fit into a CompressedGlyph record
1749 * in SimpleGlyph format, we use an array of DetailedGlyphs instead.
1751 struct DetailedGlyph
{
1752 /** The glyphID, or the Unicode character
1753 * if this is a missing glyph */
1755 /** The advance, x-offset and y-offset of the glyph, in appunits
1756 * mAdvance is in the text direction (RTL or LTR)
1757 * mXOffset is always from left to right
1758 * mYOffset is always from bottom to top */
1760 float mXOffset
, mYOffset
;
1763 // The text is divided into GlyphRuns as necessary
1765 nsRefPtr
<gfxFont
> mFont
; // never null
1766 PRUint32 mCharacterOffset
; // into original UTF16 string
1769 class THEBES_API GlyphRunIterator
{
1771 GlyphRunIterator(gfxTextRun
*aTextRun
, PRUint32 aStart
, PRUint32 aLength
)
1772 : mTextRun(aTextRun
), mStartOffset(aStart
), mEndOffset(aStart
+ aLength
) {
1773 mNextIndex
= mTextRun
->FindFirstGlyphRunContaining(aStart
);
1776 GlyphRun
*GetGlyphRun() { return mGlyphRun
; }
1777 PRUint32
GetStringStart() { return mStringStart
; }
1778 PRUint32
GetStringEnd() { return mStringEnd
; }
1780 gfxTextRun
*mTextRun
;
1781 GlyphRun
*mGlyphRun
;
1782 PRUint32 mStringStart
;
1783 PRUint32 mStringEnd
;
1784 PRUint32 mNextIndex
;
1785 PRUint32 mStartOffset
;
1786 PRUint32 mEndOffset
;
1789 class GlyphRunOffsetComparator
{
1791 PRBool
Equals(const GlyphRun
& a
,
1792 const GlyphRun
& b
) const
1794 return a
.mCharacterOffset
== b
.mCharacterOffset
;
1797 PRBool
LessThan(const GlyphRun
& a
,
1798 const GlyphRun
& b
) const
1800 return a
.mCharacterOffset
< b
.mCharacterOffset
;
1804 friend class GlyphRunIterator
;
1805 friend class FontSelector
;
1807 // API for setting up the textrun glyphs. Should only be called by
1808 // things that construct textruns.
1810 * We've found a run of text that should use a particular font. Call this
1811 * only during initialization when font substitution has been computed.
1812 * Call it before setting up the glyphs for the characters in this run;
1813 * SetMissingGlyph requires that the correct glyphrun be installed.
1815 * If aForceNewRun, a new glyph run will be added, even if the
1816 * previously added run uses the same font. If glyph runs are
1817 * added out of strictly increasing aStartCharIndex order (via
1818 * force), then SortGlyphRuns must be called after all glyph runs
1819 * are added before any further operations are performed with this
1822 nsresult
AddGlyphRun(gfxFont
*aFont
, PRUint32 aStartCharIndex
, PRBool aForceNewRun
= PR_FALSE
);
1823 void ResetGlyphRuns() { mGlyphRuns
.Clear(); }
1824 void SortGlyphRuns();
1825 void SanitizeGlyphRuns();
1827 // Call the following glyph-setters during initialization or during reshaping
1828 // only. It is OK to overwrite existing data for a character.
1830 * Set the glyph data for a character. aGlyphs may be null if aGlyph is a
1831 * simple glyph or has no associated glyphs. If non-null the data is copied,
1832 * the caller retains ownership.
1834 void SetSimpleGlyph(PRUint32 aCharIndex
, CompressedGlyph aGlyph
) {
1835 NS_ASSERTION(aGlyph
.IsSimpleGlyph(), "Should be a simple glyph here");
1836 if (mCharacterGlyphs
) {
1837 mCharacterGlyphs
[aCharIndex
] = aGlyph
;
1839 if (mDetailedGlyphs
) {
1840 mDetailedGlyphs
[aCharIndex
] = nsnull
;
1843 void SetGlyphs(PRUint32 aCharIndex
, CompressedGlyph aGlyph
,
1844 const DetailedGlyph
*aGlyphs
);
1845 void SetMissingGlyph(PRUint32 aCharIndex
, PRUint32 aUnicodeChar
);
1846 void SetSpaceGlyph(gfxFont
*aFont
, gfxContext
*aContext
, PRUint32 aCharIndex
);
1848 // If the character at aIndex is default-ignorable, set the glyph
1849 // to be invisible-missing and return TRUE, else return FALSE
1850 PRBool
FilterIfIgnorable(PRUint32 aIndex
);
1853 * Prefetch all the glyph extents needed to ensure that Measure calls
1854 * on this textrun not requesting tight boundingBoxes will succeed. Note
1855 * that some glyph extents might not be fetched due to OOM or other
1858 void FetchGlyphExtents(gfxContext
*aRefContext
);
1860 // API for access to the raw glyph data, needed by gfxFont::Draw
1861 // and gfxFont::GetBoundingBox
1862 const CompressedGlyph
*GetCharacterGlyphs() { return mCharacterGlyphs
; }
1863 const DetailedGlyph
*GetDetailedGlyphs(PRUint32 aCharIndex
) {
1864 return mDetailedGlyphs
? mDetailedGlyphs
[aCharIndex
].get() : nsnull
;
1866 PRBool
HasDetailedGlyphs() { return mDetailedGlyphs
.get() != nsnull
; }
1867 PRUint32
CountMissingGlyphs();
1868 const GlyphRun
*GetGlyphRuns(PRUint32
*aNumGlyphRuns
) {
1869 *aNumGlyphRuns
= mGlyphRuns
.Length();
1870 return mGlyphRuns
.Elements();
1872 // Returns the index of the GlyphRun containing the given offset.
1873 // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
1874 PRUint32
FindFirstGlyphRunContaining(PRUint32 aOffset
);
1875 // Copy glyph data for a range of characters from aSource to this
1876 // textrun. If aStealData is true then we actually steal the glyph data,
1877 // setting the data in aSource to "missing". aDest should be in the last
1879 virtual void CopyGlyphDataFrom(gfxTextRun
*aSource
, PRUint32 aStart
,
1880 PRUint32 aLength
, PRUint32 aDest
,
1883 nsExpirationState
*GetExpirationState() { return &mExpirationState
; }
1885 struct LigatureData
{
1886 // textrun offsets of the start and end of the containing ligature
1887 PRUint32 mLigatureStart
;
1888 PRUint32 mLigatureEnd
;
1889 // appunits advance to the start of the ligature part within the ligature;
1890 // never includes any spacing
1891 gfxFloat mPartAdvance
;
1892 // appunits width of the ligature part; includes before-spacing
1893 // when the part is at the start of the ligature, and after-spacing
1894 // when the part is as the end of the ligature
1895 gfxFloat mPartWidth
;
1897 PRPackedBool mClipBeforePart
;
1898 PRPackedBool mClipAfterPart
;
1901 // user font set generation when text run was created
1902 PRUint64
GetUserFontSetGeneration() { return mUserFontSetGeneration
; }
1905 // number of entries referencing this textrun in the gfxTextRunWordCache
1906 PRUint32 mCachedWords
;
1907 // generation of gfxTextRunWordCache that refers to this textrun;
1908 // if the cache gets cleared, then mCachedWords is no longer meaningful
1909 PRUint32 mCacheGeneration
;
1911 void Dump(FILE* aOutput
);
1914 // post-process glyph advances to deal with synthetic bolding
1915 void AdjustAdvancesForSyntheticBold(PRUint32 aStart
, PRUint32 aLength
);
1919 * Initializes the textrun to blank.
1920 * @param aGlyphStorage preallocated array of CompressedGlyph[aLength]
1921 * for the textrun to use; if aText is not persistent, then it has also
1922 * been appended to this array, so it must NOT be freed separately.
1924 gfxTextRun(const gfxTextRunFactory::Parameters
*aParams
, const void *aText
,
1925 PRUint32 aLength
, gfxFontGroup
*aFontGroup
, PRUint32 aFlags
,
1926 CompressedGlyph
*aGlyphStorage
);
1929 * Helper for the Create() factory method to allocate the required
1930 * glyph storage, and copy the text (modifying the aText parameter)
1931 * if it is not flagged as persistent.
1933 static CompressedGlyph
* AllocateStorage(const void*& aText
,
1938 // **** general helpers ****
1940 // Allocate aCount DetailedGlyphs for the given index
1941 DetailedGlyph
*AllocateDetailedGlyphs(PRUint32 aCharIndex
, PRUint32 aCount
);
1943 // Spacing for characters outside the range aSpacingStart/aSpacingEnd
1944 // is assumed to be zero; such characters are not passed to aProvider.
1945 // This is useful to protect aProvider from being passed character indices
1946 // it is not currently able to handle.
1947 PRBool
GetAdjustedSpacingArray(PRUint32 aStart
, PRUint32 aEnd
,
1948 PropertyProvider
*aProvider
,
1949 PRUint32 aSpacingStart
, PRUint32 aSpacingEnd
,
1950 nsTArray
<PropertyProvider::Spacing
> *aSpacing
);
1952 // **** ligature helpers ****
1953 // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
1954 // to handle requests that begin or end inside a ligature)
1956 // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
1957 LigatureData
ComputeLigatureData(PRUint32 aPartStart
, PRUint32 aPartEnd
,
1958 PropertyProvider
*aProvider
);
1959 gfxFloat
ComputePartialLigatureWidth(PRUint32 aPartStart
, PRUint32 aPartEnd
,
1960 PropertyProvider
*aProvider
);
1961 void DrawPartialLigature(gfxFont
*aFont
, gfxContext
*aCtx
, PRUint32 aStart
,
1962 PRUint32 aEnd
, const gfxRect
*aDirtyRect
, gfxPoint
*aPt
,
1963 PropertyProvider
*aProvider
);
1964 // Advance aStart to the start of the nearest ligature; back up aEnd
1965 // to the nearest ligature end; may result in *aStart == *aEnd
1966 void ShrinkToLigatureBoundaries(PRUint32
*aStart
, PRUint32
*aEnd
);
1967 // result in appunits
1968 gfxFloat
GetPartialLigatureWidth(PRUint32 aStart
, PRUint32 aEnd
, PropertyProvider
*aProvider
);
1969 void AccumulatePartialLigatureMetrics(gfxFont
*aFont
,
1970 PRUint32 aStart
, PRUint32 aEnd
,
1971 gfxFont::BoundingBoxType aBoundingBoxType
,
1972 gfxContext
*aRefContext
,
1973 PropertyProvider
*aProvider
,
1976 // **** measurement helper ****
1977 void AccumulateMetricsForRun(gfxFont
*aFont
, PRUint32 aStart
, PRUint32 aEnd
,
1978 gfxFont::BoundingBoxType aBoundingBoxType
,
1979 gfxContext
*aRefContext
,
1980 PropertyProvider
*aProvider
,
1981 PRUint32 aSpacingStart
, PRUint32 aSpacingEnd
,
1984 // **** drawing helper ****
1985 void DrawGlyphs(gfxFont
*aFont
, gfxContext
*aContext
, PRBool aDrawToPath
,
1986 gfxPoint
*aPt
, PRUint32 aStart
, PRUint32 aEnd
,
1987 PropertyProvider
*aProvider
,
1988 PRUint32 aSpacingStart
, PRUint32 aSpacingEnd
);
1990 // All our glyph data is in logical order, not visual.
1991 // mCharacterGlyphs is allocated by the factory that creates the textrun,
1992 // to avoid the possibility of failure during the constructor;
1993 // however, ownership passes to the textrun during construction and so
1994 // it must be deleted in the destructor.
1995 CompressedGlyph
* mCharacterGlyphs
;
1996 nsAutoArrayPtr
<nsAutoArrayPtr
<DetailedGlyph
> > mDetailedGlyphs
; // only non-null if needed
1997 // XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*,
1998 // for smaller size especially in the super-common one-glyphrun case
1999 nsAutoTArray
<GlyphRun
,1> mGlyphRuns
;
2000 // When TEXT_IS_8BIT is set, we use mSingle, otherwise we use mDouble.
2001 // When TEXT_IS_PERSISTENT is set, we don't own the text, otherwise we
2002 // own the text. When we own the text, it's allocated fused with the
2003 // mCharacterGlyphs array, and therefore need not be explicitly deleted.
2004 // This text is not null-terminated.
2006 const PRUint8
*mSingle
;
2007 const PRUnichar
*mDouble
;
2010 gfxFontGroup
*mFontGroup
; // addrefed
2011 gfxSkipChars mSkipChars
;
2012 nsExpirationState mExpirationState
;
2013 PRUint32 mAppUnitsPerDevUnit
;
2015 PRUint32 mCharacterCount
;
2017 PRUint64 mUserFontSetGeneration
; // user font set generation when text run created
2020 class THEBES_API gfxFontGroup
: public gfxTextRunFactory
{
2022 static void Shutdown(); // platform must call this to release the languageAtomService
2024 gfxFontGroup(const nsAString
& aFamilies
, const gfxFontStyle
*aStyle
, gfxUserFontSet
*aUserFontSet
= nsnull
);
2026 virtual ~gfxFontGroup();
2028 virtual gfxFont
*GetFontAt(PRInt32 i
) {
2029 // If it turns out to be hard for all clients that cache font
2030 // groups to call UpdateFontList at appropriate times, we could
2031 // instead consider just calling UpdateFontList from someplace
2032 // more central (such as here).
2033 NS_ASSERTION(!mUserFontSet
|| mCurrGeneration
== GetGeneration(),
2034 "Whoever was caching this font group should have "
2035 "called UpdateFontList on it");
2036 NS_ASSERTION(mFonts
.Length() > PRUint32(i
),
2037 "Requesting a font index that doesn't exist");
2039 return static_cast<gfxFont
*>(mFonts
[i
]);
2041 virtual PRUint32
FontListLength() const {
2042 return mFonts
.Length();
2045 PRBool
Equals(const gfxFontGroup
& other
) const {
2046 return mFamilies
.Equals(other
.mFamilies
) &&
2047 mStyle
.Equals(other
.mStyle
);
2050 const gfxFontStyle
*GetStyle() const { return &mStyle
; }
2052 virtual gfxFontGroup
*Copy(const gfxFontStyle
*aStyle
);
2055 * The listed characters should not be passed in to MakeTextRun and should
2056 * be treated as invisible and zero-width.
2058 static PRBool
IsInvalidChar(PRUnichar ch
);
2061 * Make a textrun for an empty string. This is fast; if you call it,
2062 * don't bother caching the result.
2064 gfxTextRun
*MakeEmptyTextRun(const Parameters
*aParams
, PRUint32 aFlags
);
2066 * Make a textrun for a single ASCII space. This is fast; if you call it,
2067 * don't bother caching the result.
2069 gfxTextRun
*MakeSpaceTextRun(const Parameters
*aParams
, PRUint32 aFlags
);
2072 * Make a textrun for a given string.
2073 * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
2074 * textrun will copy it.
2075 * This calls FetchGlyphExtents on the textrun.
2077 virtual gfxTextRun
*MakeTextRun(const PRUnichar
*aString
, PRUint32 aLength
,
2078 const Parameters
*aParams
, PRUint32 aFlags
);
2080 * Make a textrun for a given string.
2081 * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
2082 * textrun will copy it.
2083 * This calls FetchGlyphExtents on the textrun.
2085 virtual gfxTextRun
*MakeTextRun(const PRUint8
*aString
, PRUint32 aLength
,
2086 const Parameters
*aParams
, PRUint32 aFlags
);
2088 /* helper function for splitting font families on commas and
2089 * calling a function for each family to fill the mFonts array
2091 typedef PRBool (*FontCreationCallback
) (const nsAString
& aName
,
2092 const nsACString
& aGenericName
,
2094 PRBool
ForEachFont(const nsAString
& aFamilies
,
2096 FontCreationCallback fc
,
2098 PRBool
ForEachFont(FontCreationCallback fc
, void *closure
);
2101 * Check whether a given font (specified by its gfxFontEntry)
2102 * is already in the fontgroup's list of actual fonts
2104 PRBool
HasFont(const gfxFontEntry
*aFontEntry
);
2106 const nsString
& GetFamilies() { return mFamilies
; }
2108 // This returns the preferred underline for this font group.
2109 // Some CJK fonts have wrong underline offset in its metrics.
2110 // If this group has such "bad" font, each platform's gfxFontGroup initialized mUnderlineOffset.
2111 // The value should be lower value of first font's metrics and the bad font's metrics.
2112 // Otherwise, this returns from first font's metrics.
2113 enum { UNDERLINE_OFFSET_NOT_SET
= PR_INT16_MAX
};
2114 virtual gfxFloat
GetUnderlineOffset() {
2115 if (mUnderlineOffset
== UNDERLINE_OFFSET_NOT_SET
)
2116 mUnderlineOffset
= GetFontAt(0)->GetMetrics().underlineOffset
;
2117 return mUnderlineOffset
;
2120 already_AddRefed
<gfxFont
> FindFontForChar(PRUint32 ch
, PRUint32 prevCh
, PRUint32 nextCh
, gfxFont
*aPrevMatchedFont
);
2122 // search through pref fonts for a character, return nsnull if no matching pref font
2123 virtual already_AddRefed
<gfxFont
> WhichPrefFontSupportsChar(PRUint32 aCh
);
2125 virtual already_AddRefed
<gfxFont
> WhichSystemFontSupportsChar(PRUint32 aCh
);
2127 void ComputeRanges(nsTArray
<gfxTextRange
>& mRanges
, const PRUnichar
*aString
, PRUint32 begin
, PRUint32 end
);
2129 gfxUserFontSet
* GetUserFontSet();
2131 // With downloadable fonts, the composition of the font group can change as fonts are downloaded
2132 // for each change in state of the user font set, the generation value is bumped to avoid picking up
2133 // previously created text runs in the text run word cache. For font groups based on stylesheets
2134 // with no @font-face rule, this always returns 0.
2135 PRUint64
GetGeneration();
2137 // If there is a user font set, check to see whether the font list or any
2138 // caches need updating.
2139 virtual void UpdateFontList();
2143 gfxFontStyle mStyle
;
2144 nsTArray
< nsRefPtr
<gfxFont
> > mFonts
;
2145 gfxFloat mUnderlineOffset
;
2147 gfxUserFontSet
* mUserFontSet
;
2148 PRUint64 mCurrGeneration
; // track the current user font set generation, rebuild font list if needed
2150 // cache the most recent pref font to avoid general pref font lookup
2151 nsRefPtr
<gfxFontFamily
> mLastPrefFamily
;
2152 nsRefPtr
<gfxFont
> mLastPrefFont
;
2153 eFontPrefLang mLastPrefLang
; // lang group for last pref font
2154 PRBool mLastPrefFirstFont
; // is this the first font in the list of pref fonts for this lang group?
2155 eFontPrefLang mPageLang
;
2157 // Used for construction/destruction. Not intended to change the font set
2158 // as invalidation of font lists and caches is not considered.
2159 void SetUserFontSet(gfxUserFontSet
*aUserFontSet
);
2161 // Initialize the list of fonts
2162 void BuildFontList();
2164 // Init this font group's font metrics. If there no bad fonts, you don't need to call this.
2165 // But if there are one or more bad fonts which have bad underline offset,
2166 // you should call this with the *first* bad font.
2167 void InitMetricsForBadFont(gfxFont
* aBadFont
);
2169 // Set up the textrun glyphs, by finding script and font ranges
2170 // and calling each font's InitTextRun() as appropriate
2171 void InitTextRun(gfxContext
*aContext
,
2172 gfxTextRun
*aTextRun
,
2173 const PRUnichar
*aString
,
2176 // InitTextRun helper to handle a single script run
2177 void InitTextRun(gfxContext
*aContext
,
2178 gfxTextRun
*aTextRun
,
2179 const PRUnichar
*aString
,
2180 PRUint32 aTotalLength
,
2181 PRUint32 aScriptRunStart
,
2182 PRUint32 aScriptRunEnd
,
2183 PRInt32 aRunScript
);
2185 /* If aResolveGeneric is true, then CSS/Gecko generic family names are
2186 * replaced with preferred fonts.
2188 * If aResolveFontName is true then fc() is called only for existing fonts
2189 * and with actual font names. If false then fc() is called with each
2190 * family name in aFamilies (after resolving CSS/Gecko generic family names
2191 * if aResolveGeneric).
2193 PRBool
ForEachFontInternal(const nsAString
& aFamilies
,
2195 PRBool aResolveGeneric
,
2196 PRBool aResolveFontName
,
2197 FontCreationCallback fc
,
2200 static PRBool
FontResolverProc(const nsAString
& aName
, void *aClosure
);
2202 static PRBool
FindPlatformFont(const nsAString
& aName
,
2203 const nsACString
& aGenericName
,
2206 inline gfxFont
* WhichFontSupportsChar(nsTArray
< nsRefPtr
<gfxFont
> >& aFontList
, PRUint32 aCh
) {
2207 PRUint32 len
= aFontList
.Length();
2208 for (PRUint32 i
= 0; i
< len
; i
++) {
2209 gfxFont
* font
= aFontList
.ElementAt(i
);
2210 if (font
&& font
->HasCharacter(aCh
))
2216 static NS_HIDDEN_(nsILanguageAtomService
*) gLangService
;