1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef nsMathMLFrame_h___
8 #define nsMathMLFrame_h___
9 
10 #include "mozilla/Attributes.h"
11 #include "nsFontMetrics.h"
12 #include "nsMathMLOperators.h"
13 #include "nsIMathMLFrame.h"
14 #include "nsBoundingMetrics.h"
15 #include "nsIFrame.h"
16 
17 class nsMathMLChar;
18 class nsCSSValue;
19 class nsDisplayListSet;
20 
21 // Concrete base class with default methods that derived MathML frames can
22 // override
23 class nsMathMLFrame : public nsIMathMLFrame {
24  public:
25   // nsIMathMLFrame ---
26 
IsSpaceLike()27   virtual bool IsSpaceLike() override {
28     return NS_MATHML_IS_SPACE_LIKE(mPresentationData.flags);
29   }
30 
31   NS_IMETHOD
GetBoundingMetrics(nsBoundingMetrics & aBoundingMetrics)32   GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) override {
33     aBoundingMetrics = mBoundingMetrics;
34     return NS_OK;
35   }
36 
37   NS_IMETHOD
SetBoundingMetrics(const nsBoundingMetrics & aBoundingMetrics)38   SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics) override {
39     mBoundingMetrics = aBoundingMetrics;
40     return NS_OK;
41   }
42 
43   NS_IMETHOD
SetReference(const nsPoint & aReference)44   SetReference(const nsPoint& aReference) override {
45     mReference = aReference;
46     return NS_OK;
47   }
48 
49   virtual eMathMLFrameType GetMathMLFrameType() override;
50 
51   NS_IMETHOD
Stretch(mozilla::gfx::DrawTarget * aDrawTarget,nsStretchDirection aStretchDirection,nsBoundingMetrics & aContainerSize,mozilla::ReflowOutput & aDesiredStretchSize)52   Stretch(mozilla::gfx::DrawTarget* aDrawTarget,
53           nsStretchDirection aStretchDirection,
54           nsBoundingMetrics& aContainerSize,
55           mozilla::ReflowOutput& aDesiredStretchSize) override {
56     return NS_OK;
57   }
58 
59   NS_IMETHOD
GetEmbellishData(nsEmbellishData & aEmbellishData)60   GetEmbellishData(nsEmbellishData& aEmbellishData) override {
61     aEmbellishData = mEmbellishData;
62     return NS_OK;
63   }
64 
65   NS_IMETHOD
GetPresentationData(nsPresentationData & aPresentationData)66   GetPresentationData(nsPresentationData& aPresentationData) override {
67     aPresentationData = mPresentationData;
68     return NS_OK;
69   }
70 
71   NS_IMETHOD
72   InheritAutomaticData(nsIFrame* aParent) override;
73 
74   NS_IMETHOD
TransmitAutomaticData()75   TransmitAutomaticData() override { return NS_OK; }
76 
77   NS_IMETHOD
78   UpdatePresentationData(uint32_t aFlagsValues,
79                          uint32_t aFlagsToUpdate) override;
80 
81   NS_IMETHOD
UpdatePresentationDataFromChildAt(int32_t aFirstIndex,int32_t aLastIndex,uint32_t aFlagsValues,uint32_t aFlagsToUpdate)82   UpdatePresentationDataFromChildAt(int32_t aFirstIndex, int32_t aLastIndex,
83                                     uint32_t aFlagsValues,
84                                     uint32_t aFlagsToUpdate) override {
85     return NS_OK;
86   }
87 
ScriptIncrement(nsIFrame * aFrame)88   uint8_t ScriptIncrement(nsIFrame* aFrame) override { return 0; }
89 
IsMrowLike()90   bool IsMrowLike() override { return false; }
91 
92   // helper to get the mEmbellishData of a frame
93   // The MathML REC precisely defines an "embellished operator" as:
94   // - an <mo> element;
95   // - or one of the elements <msub>, <msup>, <msubsup>, <munder>, <mover>,
96   //   <munderover>, <mmultiscripts>, <mfrac>, or <semantics>, whose first
97   //   argument exists and is an embellished operator;
98   //- or one of the elements <mstyle>, <mphantom>, or <mpadded>, such that
99   //   an <mrow> containing the same arguments would be an embellished
100   //   operator;
101   // - or an <maction> element whose selected subexpression exists and is an
102   //   embellished operator;
103   // - or an <mrow> whose arguments consist (in any order) of one embellished
104   //   operator and zero or more spacelike elements.
105   static void GetEmbellishDataFrom(nsIFrame* aFrame,
106                                    nsEmbellishData& aEmbellishData);
107 
108   // helper to get the presentation data of a frame. If aClimbTree is
109   // set to true and the frame happens to be surrounded by non-MathML
110   // helper frames needed for its support, we walk up the frame hierarchy
111   // until we reach a MathML ancestor or the <root> math element.
112   static void GetPresentationDataFrom(nsIFrame* aFrame,
113                                       nsPresentationData& aPresentationData,
114                                       bool aClimbTree = true);
115 
116   // utilities to parse and retrieve numeric values in CSS units
117   // All values are stored in twips.
118   // @pre  aLengthValue is the default length value of the attribute.
119   // @post aLengthValue is the length value computed from the attribute.
120   static void ParseNumericValue(const nsString& aString, nscoord* aLengthValue,
121                                 uint32_t aFlags, nsPresContext* aPresContext,
122                                 mozilla::ComputedStyle* aComputedStyle,
123                                 float aFontSizeInflation);
124 
125   static nscoord CalcLength(nsPresContext* aPresContext,
126                             mozilla::ComputedStyle* aComputedStyle,
127                             const nsCSSValue& aCSSValue,
128                             float aFontSizeInflation);
129 
GetMathMLFrameTypeFor(nsIFrame * aFrame)130   static eMathMLFrameType GetMathMLFrameTypeFor(nsIFrame* aFrame) {
131     if (aFrame->IsFrameOfType(nsIFrame::eMathML)) {
132       nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
133       if (mathMLFrame) return mathMLFrame->GetMathMLFrameType();
134     }
135     return eMathMLFrameType_UNKNOWN;
136   }
137 
138   // estimate of the italic correction
GetItalicCorrection(nsBoundingMetrics & aBoundingMetrics,nscoord & aItalicCorrection)139   static void GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics,
140                                   nscoord& aItalicCorrection) {
141     aItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width;
142     if (0 > aItalicCorrection) {
143       aItalicCorrection = 0;
144     }
145   }
146 
GetItalicCorrection(nsBoundingMetrics & aBoundingMetrics,nscoord & aLeftItalicCorrection,nscoord & aRightItalicCorrection)147   static void GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics,
148                                   nscoord& aLeftItalicCorrection,
149                                   nscoord& aRightItalicCorrection) {
150     aRightItalicCorrection =
151         aBoundingMetrics.rightBearing - aBoundingMetrics.width;
152     if (0 > aRightItalicCorrection) {
153       aRightItalicCorrection = 0;
154     }
155     aLeftItalicCorrection = -aBoundingMetrics.leftBearing;
156     if (0 > aLeftItalicCorrection) {
157       aLeftItalicCorrection = 0;
158     }
159   }
160 
161   // helper methods for getting sup/subdrop's from a child
162   static void GetSubDropFromChild(nsIFrame* aChild, nscoord& aSubDrop,
163                                   float aFontSizeInflation);
164 
165   static void GetSupDropFromChild(nsIFrame* aChild, nscoord& aSupDrop,
166                                   float aFontSizeInflation);
167 
GetSkewCorrectionFromChild(nsIFrame * aChild,nscoord & aSkewCorrection)168   static void GetSkewCorrectionFromChild(nsIFrame* aChild,
169                                          nscoord& aSkewCorrection) {
170     // default is 0
171     // individual classes should over-ride this method if necessary
172     aSkewCorrection = 0;
173   }
174 
175   // 2 levels of subscript shifts
GetSubScriptShifts(nsFontMetrics * fm,nscoord & aSubScriptShift1,nscoord & aSubScriptShift2)176   static void GetSubScriptShifts(nsFontMetrics* fm, nscoord& aSubScriptShift1,
177                                  nscoord& aSubScriptShift2) {
178     nscoord xHeight = fm->XHeight();
179     aSubScriptShift1 = NSToCoordRound(150.000f / 430.556f * xHeight);
180     aSubScriptShift2 = NSToCoordRound(247.217f / 430.556f * xHeight);
181   }
182 
183   // 3 levels of superscript shifts
GetSupScriptShifts(nsFontMetrics * fm,nscoord & aSupScriptShift1,nscoord & aSupScriptShift2,nscoord & aSupScriptShift3)184   static void GetSupScriptShifts(nsFontMetrics* fm, nscoord& aSupScriptShift1,
185                                  nscoord& aSupScriptShift2,
186                                  nscoord& aSupScriptShift3) {
187     nscoord xHeight = fm->XHeight();
188     aSupScriptShift1 = NSToCoordRound(412.892f / 430.556f * xHeight);
189     aSupScriptShift2 = NSToCoordRound(362.892f / 430.556f * xHeight);
190     aSupScriptShift3 = NSToCoordRound(288.889f / 430.556f * xHeight);
191   }
192 
193   // these are TeX specific params not found in ordinary fonts
194 
GetSubDrop(nsFontMetrics * fm,nscoord & aSubDrop)195   static void GetSubDrop(nsFontMetrics* fm, nscoord& aSubDrop) {
196     nscoord xHeight = fm->XHeight();
197     aSubDrop = NSToCoordRound(50.000f / 430.556f * xHeight);
198   }
199 
GetSupDrop(nsFontMetrics * fm,nscoord & aSupDrop)200   static void GetSupDrop(nsFontMetrics* fm, nscoord& aSupDrop) {
201     nscoord xHeight = fm->XHeight();
202     aSupDrop = NSToCoordRound(386.108f / 430.556f * xHeight);
203   }
204 
GetNumeratorShifts(nsFontMetrics * fm,nscoord & numShift1,nscoord & numShift2,nscoord & numShift3)205   static void GetNumeratorShifts(nsFontMetrics* fm, nscoord& numShift1,
206                                  nscoord& numShift2, nscoord& numShift3) {
207     nscoord xHeight = fm->XHeight();
208     numShift1 = NSToCoordRound(676.508f / 430.556f * xHeight);
209     numShift2 = NSToCoordRound(393.732f / 430.556f * xHeight);
210     numShift3 = NSToCoordRound(443.731f / 430.556f * xHeight);
211   }
212 
GetDenominatorShifts(nsFontMetrics * fm,nscoord & denShift1,nscoord & denShift2)213   static void GetDenominatorShifts(nsFontMetrics* fm, nscoord& denShift1,
214                                    nscoord& denShift2) {
215     nscoord xHeight = fm->XHeight();
216     denShift1 = NSToCoordRound(685.951f / 430.556f * xHeight);
217     denShift2 = NSToCoordRound(344.841f / 430.556f * xHeight);
218   }
219 
GetEmHeight(nsFontMetrics * fm,nscoord & emHeight)220   static void GetEmHeight(nsFontMetrics* fm, nscoord& emHeight) {
221 #if 0
222     // should switch to this API in order to scale with changes of TextZoom
223     emHeight = fm->EmHeight();
224 #else
225     emHeight = fm->Font().size.ToAppUnits();
226 #endif
227   }
228 
GetAxisHeight(nsFontMetrics * fm,nscoord & axisHeight)229   static void GetAxisHeight(nsFontMetrics* fm, nscoord& axisHeight) {
230     axisHeight = NSToCoordRound(250.000f / 430.556f * fm->XHeight());
231   }
232 
GetBigOpSpacings(nsFontMetrics * fm,nscoord & bigOpSpacing1,nscoord & bigOpSpacing2,nscoord & bigOpSpacing3,nscoord & bigOpSpacing4,nscoord & bigOpSpacing5)233   static void GetBigOpSpacings(nsFontMetrics* fm, nscoord& bigOpSpacing1,
234                                nscoord& bigOpSpacing2, nscoord& bigOpSpacing3,
235                                nscoord& bigOpSpacing4, nscoord& bigOpSpacing5) {
236     nscoord xHeight = fm->XHeight();
237     bigOpSpacing1 = NSToCoordRound(111.111f / 430.556f * xHeight);
238     bigOpSpacing2 = NSToCoordRound(166.667f / 430.556f * xHeight);
239     bigOpSpacing3 = NSToCoordRound(200.000f / 430.556f * xHeight);
240     bigOpSpacing4 = NSToCoordRound(600.000f / 430.556f * xHeight);
241     bigOpSpacing5 = NSToCoordRound(100.000f / 430.556f * xHeight);
242   }
243 
GetRuleThickness(nsFontMetrics * fm,nscoord & ruleThickness)244   static void GetRuleThickness(nsFontMetrics* fm, nscoord& ruleThickness) {
245     nscoord xHeight = fm->XHeight();
246     ruleThickness = NSToCoordRound(40.000f / 430.556f * xHeight);
247   }
248 
249   // Some parameters are not accurately obtained using the x-height.
250   // Here are some slower variants to obtain the desired metrics
251   // by actually measuring some characters
252   static void GetRuleThickness(mozilla::gfx::DrawTarget* aDrawTarget,
253                                nsFontMetrics* aFontMetrics,
254                                nscoord& aRuleThickness);
255 
256   static void GetAxisHeight(mozilla::gfx::DrawTarget* aDrawTarget,
257                             nsFontMetrics* aFontMetrics, nscoord& aAxisHeight);
258 
259   static void GetRadicalParameters(nsFontMetrics* aFontMetrics,
260                                    bool aDisplayStyle,
261                                    nscoord& aRadicalRuleThickness,
262                                    nscoord& aRadicalExtraAscender,
263                                    nscoord& aRadicalVerticalGap);
264 
265  protected:
266 #if defined(DEBUG) && defined(SHOW_BOUNDING_BOX)
267   void DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
268                               const nsPoint& aPt,
269                               const nsBoundingMetrics& aMetrics,
270                               const nsDisplayListSet& aLists);
271 #endif
272 
273   /**
274    * Display a solid rectangle in the frame's text color. Used for drawing
275    * fraction separators and root/sqrt overbars.
276    */
277   void DisplayBar(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
278                   const nsRect& aRect, const nsDisplayListSet& aLists,
279                   uint32_t aIndex = 0);
280 
281   // information about the presentation policy of the frame
282   nsPresentationData mPresentationData;
283 
284   // information about a container that is an embellished operator
285   nsEmbellishData mEmbellishData;
286 
287   // Metrics that _exactly_ enclose the text of the frame
288   nsBoundingMetrics mBoundingMetrics;
289 
290   // Reference point of the frame: mReference.y is the baseline
291   nsPoint mReference;
292 };
293 
294 #endif /* nsMathMLFrame_h___ */
295