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