1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef NSFONTMETRICS__H__
7 #define NSFONTMETRICS__H__
8 
9 #include <stdint.h>                     // for uint32_t
10 #include <sys/types.h>                  // for int32_t
11 #include "gfxTextRun.h"                 // for gfxFont, gfxFontGroup
12 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
13 #include "mozilla/RefPtr.h"             // for RefPtr
14 #include "nsCOMPtr.h"                   // for nsCOMPtr
15 #include "nsCoord.h"                    // for nscoord
16 #include "nsError.h"                    // for nsresult
17 #include "nsFont.h"                     // for nsFont
18 #include "nsISupports.h"                // for NS_INLINE_DECL_REFCOUNTING
19 #include "nscore.h"                     // for char16_t
20 
21 class gfxUserFontSet;
22 class gfxTextPerfMetrics;
23 class nsDeviceContext;
24 class nsIAtom;
25 class nsRenderingContext;
26 struct nsBoundingMetrics;
27 
28 /**
29  * Font metrics
30  *
31  * This class may be somewhat misnamed. A better name might be
32  * nsFontList. The style system uses the nsFont struct for various
33  * font properties, one of which is font-family, which can contain a
34  * *list* of font names. The nsFont struct is "realized" by asking the
35  * device context to cough up an nsFontMetrics object, which contains
36  * a list of real font handles, one for each font mentioned in
37  * font-family (and for each fallback when we fall off the end of that
38  * list).
39  *
40  * The style system needs to have access to certain metrics, such as
41  * the em height (for the CSS "em" unit), and we use the first Western
42  * font's metrics for that purpose. The platform-specific
43  * implementations are expected to select non-Western fonts that "fit"
44  * reasonably well with the Western font that is loaded at Init time.
45  */
46 class nsFontMetrics final
47 {
48 public:
49     typedef gfxTextRun::Range Range;
50     typedef mozilla::gfx::DrawTarget DrawTarget;
51 
52     struct Params
53     {
54       nsIAtom* language = nullptr;
55       bool explicitLanguage = false;
56       gfxFont::Orientation orientation = gfxFont::eHorizontal;
57       gfxUserFontSet* userFontSet = nullptr;
58       gfxTextPerfMetrics* textPerf = nullptr;
59     };
60 
61     nsFontMetrics(const nsFont& aFont, const Params& aParams,
62                   nsDeviceContext *aContext);
63 
64     NS_INLINE_DECL_REFCOUNTING(nsFontMetrics)
65 
66     /**
67      * Destroy this font metrics. This breaks the association between
68      * the font metrics and the device context.
69      */
70     void Destroy();
71 
72     /**
73      * Return the font's x-height.
74      */
75     nscoord XHeight();
76 
77     /**
78      * Return the font's cap-height.
79      */
80     nscoord CapHeight();
81 
82     /**
83      * Return the font's superscript offset (the distance from the
84      * baseline to where a superscript's baseline should be placed).
85      * The value returned will be positive.
86      */
87     nscoord SuperscriptOffset();
88 
89     /**
90      * Return the font's subscript offset (the distance from the
91      * baseline to where a subscript's baseline should be placed).
92      * The value returned will be positive.
93      */
94     nscoord SubscriptOffset();
95 
96     /**
97      * Return the font's strikeout offset (the distance from the
98      * baseline to where a strikeout should be placed) and size.
99      * Positive values are above the baseline, negative below.
100      */
101     void GetStrikeout(nscoord& aOffset, nscoord& aSize);
102 
103     /**
104      * Return the font's underline offset (the distance from the
105      * baseline to where a underline should be placed) and size.
106      * Positive values are above the baseline, negative below.
107      */
108     void GetUnderline(nscoord& aOffset, nscoord& aSize);
109 
110     /**
111      * Returns the amount of internal leading for the font.
112      * This is normally the difference between the max ascent
113      * and the em ascent.
114      */
115     nscoord InternalLeading();
116 
117     /**
118      * Returns the amount of external leading for the font.
119      * em ascent(?) plus external leading is the font designer's
120      * recommended line-height for this font.
121      */
122     nscoord ExternalLeading();
123 
124     /**
125      * Returns the height of the em square.
126      * This is em ascent plus em descent.
127      */
128     nscoord EmHeight();
129 
130     /**
131      * Returns the ascent part of the em square.
132      */
133     nscoord EmAscent();
134 
135     /**
136      * Returns the descent part of the em square.
137      */
138     nscoord EmDescent();
139 
140     /**
141      * Returns the height of the bounding box.
142      * This is max ascent plus max descent.
143      */
144     nscoord MaxHeight();
145 
146     /**
147      * Returns the maximum distance characters in this font extend
148      * above the base line.
149      */
150     nscoord MaxAscent();
151 
152     /**
153      * Returns the maximum distance characters in this font extend
154      * below the base line.
155      */
156     nscoord MaxDescent();
157 
158     /**
159      * Returns the maximum character advance for the font.
160      */
161     nscoord MaxAdvance();
162 
163     /**
164      * Returns the average character width
165      */
166     nscoord AveCharWidth();
167 
168     /**
169      * Returns the often needed width of the space character
170      */
171     nscoord SpaceWidth();
172 
173     /**
174      * Returns the font associated with these metrics. The return value
175      * is only defined after Init() has been called.
176      */
Font()177     const nsFont &Font() const { return mFont; }
178 
179     /**
180      * Returns the language associated with these metrics
181      */
Language()182     nsIAtom* Language() const { return mLanguage; }
183 
184     /**
185      * Returns the orientation (horizontal/vertical) of these metrics.
186      */
Orientation()187     gfxFont::Orientation Orientation() const { return mOrientation; }
188 
189     int32_t GetMaxStringLength();
190 
191     // Get the width for this string.  aWidth will be updated with the
192     // width in points, not twips.  Callers must convert it if they
193     // want it in another format.
194     nscoord GetWidth(const char* aString, uint32_t aLength,
195                      DrawTarget* aDrawTarget);
196     nscoord GetWidth(const char16_t* aString, uint32_t aLength,
197                      DrawTarget* aDrawTarget);
198 
199     // Draw a string using this font handle on the surface passed in.
200     void DrawString(const char *aString, uint32_t aLength,
201                     nscoord aX, nscoord aY,
202                     nsRenderingContext *aContext);
203     void DrawString(const char16_t* aString, uint32_t aLength,
204                     nscoord aX, nscoord aY,
205                     nsRenderingContext *aContext,
206                     DrawTarget* aTextRunConstructionDrawTarget);
207 
208     nsBoundingMetrics GetBoundingMetrics(const char16_t *aString,
209                                          uint32_t aLength,
210                                          DrawTarget* aDrawTarget);
211 
212     // Returns the LOOSE_INK_EXTENTS bounds of the text for determing the
213     // overflow area of the string.
214     nsBoundingMetrics GetInkBoundsForVisualOverflow(const char16_t *aString,
215                                                     uint32_t aLength,
216                                                     DrawTarget* aDrawTarget);
217 
SetTextRunRTL(bool aIsRTL)218     void SetTextRunRTL(bool aIsRTL) { mTextRunRTL = aIsRTL; }
GetTextRunRTL()219     bool GetTextRunRTL() const { return mTextRunRTL; }
220 
SetVertical(bool aVertical)221     void SetVertical(bool aVertical) { mVertical = aVertical; }
GetVertical()222     bool GetVertical() const { return mVertical; }
223 
SetTextOrientation(uint8_t aTextOrientation)224     void SetTextOrientation(uint8_t aTextOrientation)
225     {
226       mTextOrientation = aTextOrientation;
227     }
GetTextOrientation()228     uint8_t GetTextOrientation() const { return mTextOrientation; }
229 
GetThebesFontGroup()230     gfxFontGroup* GetThebesFontGroup() const { return mFontGroup; }
GetUserFontSet()231     gfxUserFontSet* GetUserFontSet() const
232     {
233       return mFontGroup->GetUserFontSet();
234     }
235 
AppUnitsPerDevPixel()236     int32_t AppUnitsPerDevPixel() const { return mP2A; }
237 
238 private:
239     // Private destructor, to discourage deletion outside of Release():
240     ~nsFontMetrics();
241 
GetMetrics()242     const gfxFont::Metrics& GetMetrics() const {
243       return GetMetrics(mOrientation);
244     }
245 
246     const gfxFont::Metrics&
247     GetMetrics(const gfxFont::Orientation aFontOrientation) const;
248 
249     nsFont mFont;
250     RefPtr<gfxFontGroup> mFontGroup;
251     nsCOMPtr<nsIAtom> mLanguage;
252     nsDeviceContext* mDeviceContext;
253     int32_t mP2A;
254 
255     // The font orientation (horizontal or vertical) for which these metrics
256     // have been initialized. This determines which line metrics (ascent and
257     // descent) they will return.
258     gfxFont::Orientation mOrientation;
259 
260     // These fields may be set by clients to control the behavior of methods
261     // like GetWidth and DrawString according to the writing mode, direction
262     // and text-orientation desired.
263     bool mTextRunRTL;
264     bool mVertical;
265     uint8_t mTextOrientation;
266 };
267 
268 #endif /* NSFONTMETRICS__H__ */
269