CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / gfx / thebes / gfxFont.h
blob91dcb6e26767d347114f627457d74150557295f7
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
13 * License.
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.
21 * Contributor(s):
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 ***** */
41 #ifndef GFX_FONT_H
42 #define GFX_FONT_H
44 #include "prtypes.h"
45 #include "gfxTypes.h"
46 #include "nsString.h"
47 #include "gfxPoint.h"
48 #include "gfxFontUtils.h"
49 #include "nsTArray.h"
50 #include "nsTHashtable.h"
51 #include "nsHashKeys.h"
52 #include "gfxSkipChars.h"
53 #include "gfxRect.h"
54 #include "nsExpirationTracker.h"
55 #include "gfxFontConstants.h"
56 #include "gfxPlatform.h"
57 #include "nsIAtom.h"
58 #include "nsISupportsImpl.h"
60 #ifdef DEBUG
61 #include <stdio.h>
62 #endif
64 class gfxContext;
65 class gfxTextRun;
66 class gfxFont;
67 class gfxFontFamily;
68 class gfxFontGroup;
69 class gfxUserFontSet;
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
96 inline PRBool
97 operator<(const gfxFontFeature& a, const gfxFontFeature& b)
99 return (a.mTag < b.mTag) || ((a.mTag == b.mTag) && (a.mValue < b.mValue));
102 inline PRBool
103 operator==(const gfxFontFeature& a, const gfxFontFeature& b)
105 return (a.mTag == b.mTag) && (a.mValue == b.mValue);
109 struct THEBES_API gfxFontStyle {
110 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)
121 PRUint8 style : 7;
123 // Say that this font is a system font and therefore does not
124 // require certain fixup that we do for fonts from untrusted
125 // sources.
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.
136 PRUint16 weight;
138 // The stretch of the font (the sum of various NS_FONT_STRETCH_*
139 // constants; see gfxFontConstants.h).
140 PRInt16 stretch;
142 // The logical size of the font, in pixels
143 gfxFloat size;
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
148 // needs to be done.
149 float sizeAdjust;
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);
207 class gfxFontEntry {
208 public:
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),
224 mFamily(aFamily)
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) {
244 ReadCMAP();
246 return mHasCmapTable;
249 inline PRBool HasCharacter(PRUint32 ch) {
250 if (mCharacterMap.test(ch))
251 return PR_TRUE;
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 {
263 return PR_TRUE;
265 virtual PRBool SupportsLangGroup(nsIAtom *aLangGroup) const {
266 return PR_TRUE;
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) {
274 mFamily = aFamily;
277 const nsString& FamilyName() const;
279 already_AddRefed<gfxFont> FindOrMakeFont(const gfxFontStyle *aStyle,
280 PRBool aNeedsBold);
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);
305 nsString mName;
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;
317 PRUint16 mWeight;
318 PRInt16 mStretch;
320 PRPackedBool mHasCmapTable;
321 PRPackedBool mCmapInitialized;
322 gfxSparseBitSet mCharacterMap;
323 PRUint32 mUVSOffset;
324 nsAutoArrayPtr<PRUint8> mUVSData;
325 gfxUserFontData* mUserFontData;
327 nsTArray<gfxFontFeature> mFeatureSettings;
328 PRUint32 mLanguageOverride;
330 protected:
331 friend class gfxPlatformFontList;
332 friend class gfxMacPlatformFontList;
333 friend class gfxUserFcFontEntry;
334 friend class gfxFontFamily;
335 friend class gfxSingleFaceMacFontFamily;
337 gfxFontEntry() :
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),
351 mFamily(nsnull)
354 virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold) {
355 NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
356 return nsnull;
359 gfxFontFamily *mFamily;
361 private:
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
370 * every time.
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
380 * harfbuzz.
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
406 public:
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
429 // table.
430 hb_blob_t *
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;
442 void Clear();
444 private:
445 static void DeleteFontTableBlobData(void *aBlobData);
446 // not implemented
447 FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
449 FontTableBlobData *mSharedBlobData;
450 hb_blob_t *mBlob;
453 nsTHashtable<FontTableHashEntry> mFontTableCache;
455 gfxFontEntry(const gfxFontEntry&);
456 gfxFontEntry& operator=(const gfxFontEntry&);
460 // used when picking fallback font
461 struct FontSearch {
462 FontSearch(const PRUint32 aCharacter, gfxFont *aFont) :
463 mCh(aCharacter), mFontToMatch(aFont), mMatchRank(0), mCount(0) {
465 const PRUint32 mCh;
466 gfxFont* mFontToMatch;
467 PRInt32 mMatchRank;
468 nsRefPtr<gfxFontEntry> mBestMatch;
469 PRUint32 mCount;
472 class gfxFontFamily {
473 public:
474 NS_INLINE_DECL_REFCOUNTING(gfxFontFamily)
476 gfxFontFamily(const nsAString& aName) :
477 mName(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
536 void ReadCMAP() {
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;
547 if (mHasStyles) {
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();
562 protected:
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;
582 nsString mName;
583 nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
584 PRPackedBool mOtherFamilyNamesInitialized;
585 PRPackedBool mHasOtherFamilyNames;
586 PRPackedBool mFaceNamesInitialized;
587 PRPackedBool mHasStyles;
588 PRPackedBool mIsSimpleFamily;
589 PRPackedBool mIsBadUnderlineFamily;
591 enum {
592 // for "simple" families, the faces are stored in mAvailableFonts
593 // with fixed positions:
594 kRegularFaceIndex = 0,
595 kBoldFaceIndex = 1,
596 kItalicFaceIndex = 2,
597 kBoldItalicFaceIndex = 3,
598 // mask values for selecting face with bold and/or italic attributes
599 kBoldMask = 0x01,
600 kItalicMask = 0x02
604 struct gfxTextRange {
605 gfxTextRange(PRUint32 aStart, PRUint32 aEnd) : start(aStart), end(aEnd) { }
606 PRUint32 Length() const { return end - start; }
607 nsRefPtr<gfxFont> font;
608 PRUint32 start, end;
613 * Font cache design:
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> {
627 public:
628 enum { TIMEOUT_SECONDS = 10 };
629 gfxFontCache()
630 : nsExpirationTracker<gfxFont,3>(TIMEOUT_SECONDS*1000) { mFonts.Init(); }
631 ~gfxFontCache() {
632 // Expire everything that has a zero refcount, so we don't leak them.
633 AgeAllGenerations();
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
639 // the tracker.
643 * Get the global gfxFontCache. You must call Init() before
644 * calling this method --- the result will not be null.
646 static gfxFontCache* GetCache() {
647 return gGlobalCache;
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
666 // amount of time.
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.
676 void Flush() {
677 mFonts.Clear();
678 AgeAllGenerations();
681 protected:
682 void DestroyFont(gfxFont *aFont);
684 static gfxFontCache *gGlobalCache;
686 struct Key {
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 {
694 public:
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) { }
702 ~HashEntry() { }
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 };
711 gfxFont* mFont;
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 {
731 public:
732 gfxGlyphExtents(PRUint32 aAppUnitsPerDevUnit) :
733 mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) {
734 MOZ_COUNT_CTOR(gfxGlyphExtents);
735 mTightGlyphExtents.Init();
737 ~gfxGlyphExtents();
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
744 // appunits.
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; }
771 private:
772 class HashEntry : public nsUint32HashKey {
773 public:
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
787 class GlyphWidths {
788 public:
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];
795 if (!bits)
796 return INVALID_WIDTH;
797 PRUint32 indexInBlock = aIndex & (BLOCK_SIZE - 1);
798 if (bits & 0x1) {
799 if (GetGlyphOffset(bits) != indexInBlock)
800 return INVALID_WIDTH;
801 return GetWidth(bits);
803 PRUint16 *widths = reinterpret_cast<PRUint16 *>(bits);
804 return widths[indexInBlock];
807 #ifdef DEBUG
808 PRUint32 ComputeSize();
809 #endif
811 ~GlyphWidths();
813 private:
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;
835 * gfxFontShaper
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 {
853 public:
854 gfxFontShaper(gfxFont *aFont)
855 : mFont(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,
865 PRUint32 aRunStart,
866 PRUint32 aRunLength,
867 PRInt32 aRunScript) = 0;
869 gfxFont *GetFont() const { return mFont; }
871 protected:
872 // the font this shaper is working with
873 gfxFont * mFont;
876 /* a SPECIFIC single font family */
877 class THEBES_API gfxFont {
878 public:
879 nsrefcnt AddRef(void) {
880 NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
881 if (mExpirationState.IsTracked()) {
882 gfxFontCache::GetCache()->RemoveObject(this);
884 ++mRefCnt;
885 NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this));
886 return mRefCnt;
888 nsrefcnt Release(void) {
889 NS_PRECONDITION(0 != mRefCnt, "dup release");
890 --mRefCnt;
891 NS_LOG_RELEASE(this, mRefCnt, "gfxFont");
892 if (mRefCnt == 0) {
893 NotifyReleased();
894 // |this| may have been deleted.
895 return 0;
897 return mRefCnt;
900 PRInt32 GetRefCount() { return mRefCnt; }
902 // options to specify the kind of AA to be used when creating a font
903 typedef enum {
904 kAntialiasDefault,
905 kAntialiasNone,
906 kAntialiasGrayscale,
907 kAntialiasSubpixel
908 } AntialiasOption;
910 protected:
911 nsAutoRefCnt mRefCnt;
913 void NotifyReleased() {
914 gfxFontCache *cache = gfxFontCache::GetCache();
915 if (cache) {
916 // Don't delete just yet; return the object to the cache for
917 // possibly recycling within some time limit
918 cache->NotifyReleased(this);
919 } else {
920 // The cache may have already been shut down.
921 delete this;
925 gfxFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
926 AntialiasOption anAAOption = kAntialiasDefault);
928 public:
929 virtual ~gfxFont();
931 PRBool Valid() const {
932 return mIsValid;
935 // options for the kind of bounding box to return from measurement
936 typedef enum {
937 LOOSE_INK_EXTENTS,
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.
941 TIGHT_INK_EXTENTS,
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
949 // beyond this.
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.
960 } BoundingBoxType;
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
969 return nsnull;
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 {
1006 return PR_FALSE;
1008 // Map unicode character to glyph ID.
1009 // Only used if ProvidesGetGlyph() returns PR_TRUE.
1010 virtual PRUint32 GetGlyph(PRUint32 unicode, PRUint32 variation_selector) {
1011 return 0;
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() {
1018 return PR_FALSE;
1021 // The return value is interpreted as a horizontal advance in 16.16 fixed
1022 // point format.
1023 virtual PRInt32 GetGlyphWidth(gfxContext *aCtx, PRUint16 aGID) {
1024 return -1;
1027 // Font metrics
1028 struct Metrics {
1029 gfxFloat xHeight;
1030 gfxFloat superscriptOffset;
1031 gfxFloat subscriptOffset;
1032 gfxFloat strikeoutSize;
1033 gfxFloat strikeoutOffset;
1034 gfxFloat underlineSize;
1035 gfxFloat underlineOffset;
1037 gfxFloat internalLeading;
1038 gfxFloat externalLeading;
1040 gfxFloat emHeight;
1041 gfxFloat emAscent;
1042 gfxFloat emDescent;
1043 gfxFloat maxHeight;
1044 gfxFloat maxAscent;
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.
1064 struct Spacing {
1065 gfxFloat mBefore;
1066 gfxFloat mAfter;
1069 * Metrics for a particular string
1071 struct THEBES_API RunMetrics {
1072 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
1100 * be honoured.
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
1106 * units, really!
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,
1123 Spacing *aSpacing);
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
1132 * be non-null.
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,
1149 Spacing *aSpacing);
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) {
1179 if (!mIsValid)
1180 return PR_FALSE;
1181 return mFontEntry->HasCharacter(ch);
1184 PRUint16 GetUVSGlyph(PRUint32 aCh, PRUint32 aVS) {
1185 if (!mIsValid) {
1186 return 0;
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,
1197 PRUint32 aRunStart,
1198 PRUint32 aRunLength,
1199 PRInt32 aRunScript);
1201 protected:
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
1230 // been updated.)
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,
1259 PRUint32 aRunStart,
1260 PRUint32 aRunLength,
1261 PRInt32 aRunScript,
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)
1271 public:
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.
1275 enum {
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
1326 * other effects.
1328 TEXT_OPTIMIZE_SPEED = 0x0100
1332 * This record contains all the parameters needed to initialize a textrun.
1334 struct Parameters {
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)
1338 void *mUserData;
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
1371 * be on the test!
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
1388 * won't.
1390 class THEBES_API gfxTextRun {
1391 public:
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
1422 * linebreaks.
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 {
1446 public:
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
1473 * is returned here.
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
1499 * is returned here.
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
1552 * properly.
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
1607 * the effect of
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,
1625 Metrics *aMetrics,
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) {}
1640 // Utility getters
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");
1650 mFlags |= aFlags;
1652 void ClearFlagBits(PRUint32 aFlags) {
1653 NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
1654 "Only user flags should be mutable");
1655 mFlags &= ~aFlags;
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 {
1704 public:
1705 CompressedGlyph() { mValue = 0; }
1707 enum {
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
1712 // in appunits).
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,
1719 ADVANCE_SHIFT = 16,
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
1725 // flag bits:
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);
1779 mValue ^= toggle;
1780 return toggle;
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;
1788 return *this;
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);
1796 return *this;
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);
1805 return *this;
1807 PRUint32 GetGlyphCount() const {
1808 NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
1809 return (mValue & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT;
1812 private:
1813 PRUint32 mValue;
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 */
1823 PRUint32 mGlyphID;
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 */
1828 PRInt32 mAdvance;
1829 float mXOffset, mYOffset;
1832 // The text is divided into GlyphRuns as necessary
1833 struct GlyphRun {
1834 nsRefPtr<gfxFont> mFont; // never null
1835 PRUint32 mCharacterOffset; // into original UTF16 string
1838 class THEBES_API GlyphRunIterator {
1839 public:
1840 GlyphRunIterator(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aLength)
1841 : mTextRun(aTextRun), mStartOffset(aStart), mEndOffset(aStart + aLength) {
1842 mNextIndex = mTextRun->FindFirstGlyphRunContaining(aStart);
1844 PRBool NextRun();
1845 GlyphRun *GetGlyphRun() { return mGlyphRun; }
1846 PRUint32 GetStringStart() { return mStringStart; }
1847 PRUint32 GetStringEnd() { return mStringEnd; }
1848 private:
1849 gfxTextRun *mTextRun;
1850 GlyphRun *mGlyphRun;
1851 PRUint32 mStringStart;
1852 PRUint32 mStringEnd;
1853 PRUint32 mNextIndex;
1854 PRUint32 mStartOffset;
1855 PRUint32 mEndOffset;
1858 class GlyphRunOffsetComparator {
1859 public:
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
1889 * TextRun.
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
1922 * errors.
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
1951 // textrun.
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; }
1976 #ifdef DEBUG
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);
1984 #endif
1986 // post-process glyph advances to deal with synthetic bolding
1987 void AdjustAdvancesForSyntheticBold(PRUint32 aStart, PRUint32 aLength);
1989 protected:
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,
2006 PRUint32 aLength,
2007 PRUint32 aFlags);
2009 private:
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,
2049 Metrics *aMetrics);
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,
2057 Metrics *aMetrics);
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 {
2079 public:
2080 DetailedGlyphStore()
2081 : mLastUsed(0)
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) {
2103 ++mLastUsed;
2104 } else if (aOffset == mOffsetToIndex[0].mOffset) {
2105 mLastUsed = 0;
2106 } else if (aOffset == mOffsetToIndex[mLastUsed].mOffset) {
2107 // do nothing
2108 } else if (mLastUsed > 0 &&
2109 aOffset == mOffsetToIndex[mLastUsed - 1].mOffset) {
2110 --mLastUsed;
2111 } else {
2112 mLastUsed =
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);
2123 if (!details) {
2124 return nsnull;
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
2129 // method.
2130 if (mOffsetToIndex.Length() == 0 ||
2131 aOffset > mOffsetToIndex[mOffsetToIndex.Length() - 1].mOffset) {
2132 if (!mOffsetToIndex.AppendElement(DGRec(aOffset, detailIndex))) {
2133 return nsnull;
2135 } else {
2136 if (!mOffsetToIndex.InsertElementSorted(DGRec(aOffset, detailIndex),
2137 CompareRecordOffsets())) {
2138 return nsnull;
2141 return details;
2144 private:
2145 struct DGRec {
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.
2196 union {
2197 const PRUint8 *mSingle;
2198 const PRUnichar *mDouble;
2199 } mText;
2200 void *mUserData;
2201 gfxFontGroup *mFontGroup; // addrefed
2202 gfxSkipChars mSkipChars;
2203 nsExpirationState mExpirationState;
2204 PRUint32 mAppUnitsPerDevUnit;
2205 PRUint32 mFlags;
2206 PRUint32 mCharacterCount;
2207 PRUint32 mHashCode;
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 {
2216 public:
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,
2288 void *closure);
2289 PRBool ForEachFont(const nsAString& aFamilies,
2290 nsIAtom *aLanguage,
2291 FontCreationCallback fc,
2292 void *closure);
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;
2344 protected:
2345 nsString mFamilies;
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
2362 // timer to fire)
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,
2381 PRUint32 aLength);
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,
2402 nsIAtom *aLanguage,
2403 PRBool aResolveGeneric,
2404 PRBool aResolveFontName,
2405 FontCreationCallback fc,
2406 void *closure);
2408 static PRBool FontResolverProc(const nsAString& aName, void *aClosure);
2410 static PRBool FindPlatformFont(const nsAString& aName,
2411 const nsACString& aGenericName,
2412 void *closure);
2414 static NS_HIDDEN_(nsILanguageAtomService*) gLangService;
2416 #endif