michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsMathMLFrame_h___ michael@0: #define nsMathMLFrame_h___ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsFontMetrics.h" michael@0: #include "nsMathMLOperators.h" michael@0: #include "nsIMathMLFrame.h" michael@0: #include "nsLayoutUtils.h" michael@0: #include "nsBoundingMetrics.h" michael@0: #include "nsIFrame.h" michael@0: michael@0: class nsMathMLChar; michael@0: class nsCSSValue; michael@0: class nsDisplayListSet; michael@0: michael@0: // Concrete base class with default methods that derived MathML frames can override michael@0: class nsMathMLFrame : public nsIMathMLFrame { michael@0: public: michael@0: michael@0: // nsIMathMLFrame --- michael@0: michael@0: virtual bool michael@0: IsSpaceLike() MOZ_OVERRIDE { michael@0: return NS_MATHML_IS_SPACE_LIKE(mPresentationData.flags); michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) MOZ_OVERRIDE { michael@0: aBoundingMetrics = mBoundingMetrics; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics) MOZ_OVERRIDE { michael@0: mBoundingMetrics = aBoundingMetrics; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: SetReference(const nsPoint& aReference) MOZ_OVERRIDE { michael@0: mReference = aReference; michael@0: return NS_OK; michael@0: } michael@0: michael@0: virtual eMathMLFrameType GetMathMLFrameType() MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD michael@0: Stretch(nsRenderingContext& aRenderingContext, michael@0: nsStretchDirection aStretchDirection, michael@0: nsBoundingMetrics& aContainerSize, michael@0: nsHTMLReflowMetrics& aDesiredStretchSize) MOZ_OVERRIDE michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: GetEmbellishData(nsEmbellishData& aEmbellishData) MOZ_OVERRIDE { michael@0: aEmbellishData = mEmbellishData; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: GetPresentationData(nsPresentationData& aPresentationData) MOZ_OVERRIDE { michael@0: aPresentationData = mPresentationData; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: InheritAutomaticData(nsIFrame* aParent) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD michael@0: TransmitAutomaticData() MOZ_OVERRIDE michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHOD michael@0: UpdatePresentationData(uint32_t aFlagsValues, michael@0: uint32_t aFlagsToUpdate) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD michael@0: UpdatePresentationDataFromChildAt(int32_t aFirstIndex, michael@0: int32_t aLastIndex, michael@0: uint32_t aFlagsValues, michael@0: uint32_t aFlagsToUpdate) MOZ_OVERRIDE michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: uint8_t michael@0: ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: bool michael@0: IsMrowLike() MOZ_OVERRIDE michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: // helper to give a style context suitable for doing the stretching to the michael@0: // MathMLChar. Frame classes that use this should make the extra style contexts michael@0: // accessible to the Style System via Get/Set AdditionalStyleContext. michael@0: static void michael@0: ResolveMathMLCharStyle(nsPresContext* aPresContext, michael@0: nsIContent* aContent, michael@0: nsStyleContext* aParenStyleContext, michael@0: nsMathMLChar* aMathMLChar); michael@0: michael@0: // helper to get the mEmbellishData of a frame michael@0: // The MathML REC precisely defines an "embellished operator" as: michael@0: // - an element; michael@0: // - or one of the elements , , , , , michael@0: // , , , or , whose first michael@0: // argument exists and is an embellished operator; michael@0: //- or one of the elements , , or , such that michael@0: // an containing the same arguments would be an embellished michael@0: // operator; michael@0: // - or an element whose selected subexpression exists and is an michael@0: // embellished operator; michael@0: // - or an whose arguments consist (in any order) of one embellished michael@0: // operator and zero or more spacelike elements. michael@0: static void michael@0: GetEmbellishDataFrom(nsIFrame* aFrame, michael@0: nsEmbellishData& aEmbellishData); michael@0: michael@0: // helper to get the presentation data of a frame. If aClimbTree is michael@0: // set to true and the frame happens to be surrounded by non-MathML michael@0: // helper frames needed for its support, we walk up the frame hierarchy michael@0: // until we reach a MathML ancestor or the math element. michael@0: static void michael@0: GetPresentationDataFrom(nsIFrame* aFrame, michael@0: nsPresentationData& aPresentationData, michael@0: bool aClimbTree = true); michael@0: michael@0: // utilities to parse and retrieve numeric values in CSS units michael@0: // All values are stored in twips. michael@0: // @pre aLengthValue is the default length value of the attribute. michael@0: // @post aLengthValue is the length value computed from the attribute. michael@0: static void ParseNumericValue(const nsString& aString, michael@0: nscoord* aLengthValue, michael@0: uint32_t aFlags, michael@0: nsPresContext* aPresContext, michael@0: nsStyleContext* aStyleContext); michael@0: michael@0: static nscoord michael@0: CalcLength(nsPresContext* aPresContext, michael@0: nsStyleContext* aStyleContext, michael@0: const nsCSSValue& aCSSValue); michael@0: michael@0: static eMathMLFrameType michael@0: GetMathMLFrameTypeFor(nsIFrame* aFrame) michael@0: { michael@0: if (aFrame->IsFrameOfType(nsIFrame::eMathML)) { michael@0: nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame); michael@0: if (mathMLFrame) michael@0: return mathMLFrame->GetMathMLFrameType(); michael@0: } michael@0: return eMathMLFrameType_UNKNOWN; michael@0: } michael@0: michael@0: // estimate of the italic correction michael@0: static void michael@0: GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, michael@0: nscoord& aItalicCorrection) michael@0: { michael@0: aItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; michael@0: if (0 > aItalicCorrection) { michael@0: aItalicCorrection = 0; michael@0: } michael@0: } michael@0: michael@0: static void michael@0: GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, michael@0: nscoord& aLeftItalicCorrection, michael@0: nscoord& aRightItalicCorrection) michael@0: { michael@0: aRightItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; michael@0: if (0 > aRightItalicCorrection) { michael@0: aRightItalicCorrection = 0; michael@0: } michael@0: aLeftItalicCorrection = -aBoundingMetrics.leftBearing; michael@0: if (0 > aLeftItalicCorrection) { michael@0: aLeftItalicCorrection = 0; michael@0: } michael@0: } michael@0: michael@0: // helper methods for getting sup/subdrop's from a child michael@0: static void michael@0: GetSubDropFromChild(nsIFrame* aChild, michael@0: nscoord& aSubDrop) michael@0: { michael@0: nsRefPtr fm; michael@0: nsLayoutUtils::GetFontMetricsForFrame(aChild, getter_AddRefs(fm)); michael@0: GetSubDrop(fm, aSubDrop); michael@0: } michael@0: michael@0: static void michael@0: GetSupDropFromChild(nsIFrame* aChild, michael@0: nscoord& aSupDrop) michael@0: { michael@0: nsRefPtr fm; michael@0: nsLayoutUtils::GetFontMetricsForFrame(aChild, getter_AddRefs(fm)); michael@0: GetSupDrop(fm, aSupDrop); michael@0: } michael@0: michael@0: static void michael@0: GetSkewCorrectionFromChild(nsIFrame* aChild, michael@0: nscoord& aSkewCorrection) michael@0: { michael@0: // default is 0 michael@0: // individual classes should over-ride this method if necessary michael@0: aSkewCorrection = 0; michael@0: } michael@0: michael@0: // 2 levels of subscript shifts michael@0: static void michael@0: GetSubScriptShifts(nsFontMetrics* fm, michael@0: nscoord& aSubScriptShift1, michael@0: nscoord& aSubScriptShift2) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: aSubScriptShift1 = NSToCoordRound(150.000f/430.556f * xHeight); michael@0: aSubScriptShift2 = NSToCoordRound(247.217f/430.556f * xHeight); michael@0: } michael@0: michael@0: // 3 levels of superscript shifts michael@0: static void michael@0: GetSupScriptShifts(nsFontMetrics* fm, michael@0: nscoord& aSupScriptShift1, michael@0: nscoord& aSupScriptShift2, michael@0: nscoord& aSupScriptShift3) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: aSupScriptShift1 = NSToCoordRound(412.892f/430.556f * xHeight); michael@0: aSupScriptShift2 = NSToCoordRound(362.892f/430.556f * xHeight); michael@0: aSupScriptShift3 = NSToCoordRound(288.889f/430.556f * xHeight); michael@0: } michael@0: michael@0: // these are TeX specific params not found in ordinary fonts michael@0: michael@0: static void michael@0: GetSubDrop(nsFontMetrics* fm, michael@0: nscoord& aSubDrop) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: aSubDrop = NSToCoordRound(50.000f/430.556f * xHeight); michael@0: } michael@0: michael@0: static void michael@0: GetSupDrop(nsFontMetrics* fm, michael@0: nscoord& aSupDrop) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: aSupDrop = NSToCoordRound(386.108f/430.556f * xHeight); michael@0: } michael@0: michael@0: static void michael@0: GetNumeratorShifts(nsFontMetrics* fm, michael@0: nscoord& numShift1, michael@0: nscoord& numShift2, michael@0: nscoord& numShift3) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: numShift1 = NSToCoordRound(676.508f/430.556f * xHeight); michael@0: numShift2 = NSToCoordRound(393.732f/430.556f * xHeight); michael@0: numShift3 = NSToCoordRound(443.731f/430.556f * xHeight); michael@0: } michael@0: michael@0: static void michael@0: GetDenominatorShifts(nsFontMetrics* fm, michael@0: nscoord& denShift1, michael@0: nscoord& denShift2) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: denShift1 = NSToCoordRound(685.951f/430.556f * xHeight); michael@0: denShift2 = NSToCoordRound(344.841f/430.556f * xHeight); michael@0: } michael@0: michael@0: static void michael@0: GetEmHeight(nsFontMetrics* fm, michael@0: nscoord& emHeight) michael@0: { michael@0: #if 0 michael@0: // should switch to this API in order to scale with changes of TextZoom michael@0: emHeight = fm->EmHeight(); michael@0: #else michael@0: emHeight = NSToCoordRound(float(fm->Font().size)); michael@0: #endif michael@0: } michael@0: michael@0: static void michael@0: GetAxisHeight (nsFontMetrics* fm, michael@0: nscoord& axisHeight) michael@0: { michael@0: axisHeight = NSToCoordRound(250.000f/430.556f * fm->XHeight()); michael@0: } michael@0: michael@0: static void michael@0: GetBigOpSpacings(nsFontMetrics* fm, michael@0: nscoord& bigOpSpacing1, michael@0: nscoord& bigOpSpacing2, michael@0: nscoord& bigOpSpacing3, michael@0: nscoord& bigOpSpacing4, michael@0: nscoord& bigOpSpacing5) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: bigOpSpacing1 = NSToCoordRound(111.111f/430.556f * xHeight); michael@0: bigOpSpacing2 = NSToCoordRound(166.667f/430.556f * xHeight); michael@0: bigOpSpacing3 = NSToCoordRound(200.000f/430.556f * xHeight); michael@0: bigOpSpacing4 = NSToCoordRound(600.000f/430.556f * xHeight); michael@0: bigOpSpacing5 = NSToCoordRound(100.000f/430.556f * xHeight); michael@0: } michael@0: michael@0: static void michael@0: GetRuleThickness(nsFontMetrics* fm, michael@0: nscoord& ruleThickness) michael@0: { michael@0: nscoord xHeight = fm->XHeight(); michael@0: ruleThickness = NSToCoordRound(40.000f/430.556f * xHeight); michael@0: } michael@0: michael@0: // Some parameters are not accurately obtained using the x-height. michael@0: // Here are some slower variants to obtain the desired metrics michael@0: // by actually measuring some characters michael@0: static void michael@0: GetRuleThickness(nsRenderingContext& aRenderingContext, michael@0: nsFontMetrics* aFontMetrics, michael@0: nscoord& aRuleThickness); michael@0: michael@0: static void michael@0: GetAxisHeight(nsRenderingContext& aRenderingContext, michael@0: nsFontMetrics* aFontMetrics, michael@0: nscoord& aAxisHeight); michael@0: michael@0: protected: michael@0: #if defined(DEBUG) && defined(SHOW_BOUNDING_BOX) michael@0: nsresult DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder, michael@0: nsIFrame* aFrame, const nsPoint& aPt, michael@0: const nsBoundingMetrics& aMetrics, michael@0: const nsDisplayListSet& aLists); michael@0: #endif michael@0: michael@0: /** michael@0: * Display a solid rectangle in the frame's text color. Used for drawing michael@0: * fraction separators and root/sqrt overbars. michael@0: */ michael@0: void DisplayBar(nsDisplayListBuilder* aBuilder, michael@0: nsIFrame* aFrame, const nsRect& aRect, michael@0: const nsDisplayListSet& aLists); michael@0: michael@0: // information about the presentation policy of the frame michael@0: nsPresentationData mPresentationData; michael@0: michael@0: // information about a container that is an embellished operator michael@0: nsEmbellishData mEmbellishData; michael@0: michael@0: // Metrics that _exactly_ enclose the text of the frame michael@0: nsBoundingMetrics mBoundingMetrics; michael@0: michael@0: // Reference point of the frame: mReference.y is the baseline michael@0: nsPoint mReference; michael@0: }; michael@0: michael@0: #endif /* nsMathMLFrame_h___ */