Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
6 #ifndef nsMathMLChar_h___
7 #define nsMathMLChar_h___
9 #include "nsAutoPtr.h"
10 #include "nsMathMLOperators.h"
11 #include "nsPoint.h"
12 #include "nsRect.h"
13 #include "nsString.h"
14 #include "nsBoundingMetrics.h"
15 #include "gfxFont.h"
17 class nsGlyphTable;
18 class nsIFrame;
19 class nsDisplayListBuilder;
20 class nsDisplayListSet;
21 class nsPresContext;
22 class nsRenderingContext;
23 class nsBoundingMetrics;
24 class nsStyleContext;
25 class nsFont;
27 // Hints for Stretch() to indicate criteria for stretching
28 enum {
29 // Don't stretch
30 NS_STRETCH_NONE = 0x00,
31 // Variable size stretches
32 NS_STRETCH_VARIABLE_MASK = 0x0F,
33 NS_STRETCH_NORMAL = 0x01, // try to stretch to requested size
34 NS_STRETCH_NEARER = 0x02, // stretch very close to requested size
35 NS_STRETCH_SMALLER = 0x04, // don't stretch more than requested size
36 NS_STRETCH_LARGER = 0x08, // don't stretch less than requested size
37 // A largeop in displaystyle
38 NS_STRETCH_LARGEOP = 0x10,
39 NS_STRETCH_INTEGRAL = 0x20,
41 // Intended for internal use:
42 // Find the widest metrics that might be returned from a vertical stretch
43 NS_STRETCH_MAXWIDTH = 0x40
44 };
46 // A single glyph in our internal representation is either
47 // 1) a 'code@font' pair from the mathfontFONTFAMILY.properties table. The
48 // 'code' is interpreted as a Unicode point. The 'font' is a numeric
49 // identifier given to the font to which the glyph belongs, which is 0 for the
50 // FONTFAMILY and > 0 for 'external' fonts.
51 // 2) a glyph index from the Open Type MATH table. In that case, all the glyphs
52 // come from the font containing that table and 'font' is just set to -1.
53 struct nsGlyphCode {
54 union {
55 char16_t code[2];
56 uint32_t glyphID;
57 };
58 int8_t font;
60 bool IsGlyphID() const { return font == -1; }
62 int32_t Length() const {
63 return (IsGlyphID() || code[1] == PRUnichar('\0') ? 1 : 2);
64 }
65 bool Exists() const
66 {
67 return IsGlyphID() ? glyphID != 0 : code[0] != 0;
68 }
69 bool operator==(const nsGlyphCode& other) const
70 {
71 return (other.font == font &&
72 ((IsGlyphID() && other.glyphID == glyphID) ||
73 (!IsGlyphID() && other.code[0] == code[0] &&
74 other.code[1] == code[1])));
75 }
76 bool operator!=(const nsGlyphCode& other) const
77 {
78 return ! operator==(other);
79 }
80 };
82 // Class used to handle stretchy symbols (accent, delimiter and boundary
83 // symbols).
84 class nsMathMLChar
85 {
86 public:
87 // constructor and destructor
88 nsMathMLChar() {
89 MOZ_COUNT_CTOR(nsMathMLChar);
90 mStyleContext = nullptr;
91 mUnscaledAscent = 0;
92 mScaleX = mScaleY = 1.0;
93 mDraw = DRAW_NORMAL;
94 mMirrored = false;
95 }
97 // not a virtual destructor: this class is not intended to be subclassed
98 ~nsMathMLChar();
100 void Display(nsDisplayListBuilder* aBuilder,
101 nsIFrame* aForFrame,
102 const nsDisplayListSet& aLists,
103 uint32_t aIndex,
104 const nsRect* aSelectedRect = nullptr);
106 void PaintForeground(nsPresContext* aPresContext,
107 nsRenderingContext& aRenderingContext,
108 nsPoint aPt,
109 bool aIsSelected);
111 // This is the method called to ask the char to stretch itself.
112 // @param aContainerSize - IN - suggested size for the stretched char
113 // @param aDesiredStretchSize - OUT - the size that the char wants
114 nsresult
115 Stretch(nsPresContext* aPresContext,
116 nsRenderingContext& aRenderingContext,
117 nsStretchDirection aStretchDirection,
118 const nsBoundingMetrics& aContainerSize,
119 nsBoundingMetrics& aDesiredStretchSize,
120 uint32_t aStretchHint,
121 bool aRTL);
123 void
124 SetData(nsPresContext* aPresContext,
125 nsString& aData);
127 void
128 GetData(nsString& aData) {
129 aData = mData;
130 }
132 int32_t
133 Length() {
134 return mData.Length();
135 }
137 nsStretchDirection
138 GetStretchDirection() {
139 return mDirection;
140 }
142 // Sometimes we only want to pass the data to another routine,
143 // this function helps to avoid copying
144 const char16_t*
145 get() {
146 return mData.get();
147 }
149 void
150 GetRect(nsRect& aRect) {
151 aRect = mRect;
152 }
154 void
155 SetRect(const nsRect& aRect) {
156 mRect = aRect;
157 }
159 // Get the maximum width that the character might have after a vertical
160 // Stretch().
161 //
162 // @param aStretchHint can be the value that will be passed to Stretch().
163 // It is used to determine whether the operator is stretchy or a largeop.
164 // @param aMaxSize is the value of the "maxsize" attribute.
165 // @param aMaxSizeIsAbsolute indicates whether the aMaxSize is an absolute
166 // value in app units (true) or a multiplier of the base size (false).
167 nscoord
168 GetMaxWidth(nsPresContext* aPresContext,
169 nsRenderingContext& aRenderingContext,
170 uint32_t aStretchHint = NS_STRETCH_NORMAL,
171 float aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
172 // Perhaps just nsOperatorFlags aFlags.
173 // But need DisplayStyle for largeOp,
174 // or remove the largeop bit from flags.
175 bool aMaxSizeIsAbsolute = false);
177 // Metrics that _exactly_ enclose the char. The char *must* have *already*
178 // being stretched before you can call the GetBoundingMetrics() method.
179 // IMPORTANT: since chars have their own style contexts, and may be rendered
180 // with glyphs that are not in the parent font, just calling the default
181 // aRenderingContext.GetBoundingMetrics(aChar) can give incorrect results.
182 void
183 GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) {
184 aBoundingMetrics = mBoundingMetrics;
185 }
187 void
188 SetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) {
189 mBoundingMetrics = aBoundingMetrics;
190 }
192 // Hooks to access the extra leaf style contexts given to the MathMLChars.
193 // They provide an interface to make them accessible to the Style System via
194 // the Get/Set AdditionalStyleContext() APIs. Owners of MathMLChars
195 // should honor these APIs.
196 nsStyleContext* GetStyleContext() const;
198 void SetStyleContext(nsStyleContext* aStyleContext);
200 protected:
201 friend class nsGlyphTable;
202 friend class nsPropertiesTable;
203 friend class nsOpenTypeTable;
204 nsString mData;
206 private:
207 nsRect mRect;
208 nsStretchDirection mDirection;
209 nsBoundingMetrics mBoundingMetrics;
210 nsStyleContext* mStyleContext;
211 // mGlyphs/mBmData are arrays describing the glyphs used to draw the operator.
212 // See the drawing methods below.
213 nsAutoPtr<gfxTextRun> mGlyphs[4];
214 nsBoundingMetrics mBmData[4];
215 // mUnscaledAscent is the actual ascent of the char.
216 nscoord mUnscaledAscent;
217 // mScaleX, mScaleY are the factors by which we scale the char.
218 float mScaleX, mScaleY;
220 // mDraw indicates how we draw the stretchy operator:
221 // - DRAW_NORMAL: we render the mData string normally.
222 // - DRAW_VARIANT: we draw a larger size variant given by mGlyphs[0].
223 // - DRAW_PARTS: we assemble several parts given by mGlyphs[0], ... mGlyphs[4]
224 // XXXfredw: the MATH table can have any numbers of parts and extenders.
225 enum DrawingMethod {
226 DRAW_NORMAL, DRAW_VARIANT, DRAW_PARTS
227 };
228 DrawingMethod mDraw;
230 // mMirrored indicates whether the character is mirrored.
231 bool mMirrored;
233 class StretchEnumContext;
234 friend class StretchEnumContext;
236 // helper methods
237 bool
238 SetFontFamily(nsPresContext* aPresContext,
239 const nsGlyphTable* aGlyphTable,
240 const nsGlyphCode& aGlyphCode,
241 const nsAString& aDefaultFamily,
242 nsFont& aFont,
243 nsRefPtr<gfxFontGroup>* aFontGroup);
245 nsresult
246 StretchInternal(nsPresContext* aPresContext,
247 gfxContext* aThebesContext,
248 nsStretchDirection& aStretchDirection,
249 const nsBoundingMetrics& aContainerSize,
250 nsBoundingMetrics& aDesiredStretchSize,
251 uint32_t aStretchHint,
252 float aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
253 bool aMaxSizeIsAbsolute = false);
255 nsresult
256 PaintVertically(nsPresContext* aPresContext,
257 gfxContext* aThebesContext,
258 nsRect& aRect);
260 nsresult
261 PaintHorizontally(nsPresContext* aPresContext,
262 gfxContext* aThebesContext,
263 nsRect& aRect);
265 void
266 ApplyTransforms(gfxContext* aThebesContext, int32_t aAppUnitsPerGfxUnit,
267 nsRect &r);
268 };
270 #endif /* nsMathMLChar_h___ */