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: //#define SHOW_BOUNDING_BOX 1 michael@0: #ifndef nsIMathMLFrame_h___ michael@0: #define nsIMathMLFrame_h___ michael@0: michael@0: #include "nsQueryFrame.h" michael@0: #include "nsMathMLOperators.h" michael@0: michael@0: struct nsPresentationData; michael@0: struct nsEmbellishData; michael@0: struct nsHTMLReflowMetrics; michael@0: class nsRenderingContext; michael@0: class nsIFrame; michael@0: michael@0: // For MathML, this 'type' will be used to determine the spacing between frames michael@0: // Subclasses can return a 'type' that will give them a particular spacing michael@0: enum eMathMLFrameType { michael@0: eMathMLFrameType_UNKNOWN = -1, michael@0: eMathMLFrameType_Ordinary, michael@0: eMathMLFrameType_OperatorOrdinary, michael@0: eMathMLFrameType_OperatorInvisible, michael@0: eMathMLFrameType_OperatorUserDefined, michael@0: eMathMLFrameType_Inner, michael@0: eMathMLFrameType_ItalicIdentifier, michael@0: eMathMLFrameType_UprightIdentifier, michael@0: eMathMLFrameType_COUNT michael@0: }; michael@0: michael@0: // Abstract base class that provides additional methods for MathML frames michael@0: class nsIMathMLFrame michael@0: { michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsIMathMLFrame) michael@0: michael@0: // helper to check whether the frame is "space-like", as defined by the spec. michael@0: virtual bool IsSpaceLike() = 0; michael@0: michael@0: /* SUPPORT FOR PRECISE POSITIONING */ michael@0: /*====================================================================*/ michael@0: michael@0: /* Metrics that _exactly_ enclose the text of the frame. michael@0: * The frame *must* have *already* being reflowed, before you can call michael@0: * the GetBoundingMetrics() method. michael@0: * Note that for a frame with nested children, the bounding metrics michael@0: * will exactly enclose its children. For example, the bounding metrics michael@0: * of msub is the smallest rectangle that exactly encloses both the michael@0: * base and the subscript. michael@0: */ michael@0: NS_IMETHOD michael@0: GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) = 0; michael@0: michael@0: NS_IMETHOD michael@0: SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics) = 0; michael@0: michael@0: NS_IMETHOD michael@0: SetReference(const nsPoint& aReference) = 0; michael@0: michael@0: virtual eMathMLFrameType GetMathMLFrameType() = 0; michael@0: michael@0: /* SUPPORT FOR STRETCHY ELEMENTS */ michael@0: /*====================================================================*/ michael@0: michael@0: /* Stretch : michael@0: * Called to ask a stretchy MathML frame to stretch itself depending michael@0: * on its context. michael@0: * michael@0: * An embellished frame is treated in a special way. When it receives a michael@0: * Stretch() command, it passes the command to its embellished child and michael@0: * the stretched size is bubbled up from the inner-most frame. In other michael@0: * words, the stretch command descend through the embellished hierarchy. michael@0: * michael@0: * @param aStretchDirection [in] the direction where to attempt to michael@0: * stretch. michael@0: * @param aContainerSize [in] struct that suggests the maximumn size for michael@0: * the stretched frame. Only member data of the struct that are michael@0: * relevant to the direction are used (the rest is ignored). michael@0: * @param aDesiredStretchSize [in/out] On input the current size michael@0: * of the frame, on output the size after stretching. michael@0: */ michael@0: NS_IMETHOD michael@0: Stretch(nsRenderingContext& aRenderingContext, michael@0: nsStretchDirection aStretchDirection, michael@0: nsBoundingMetrics& aContainerSize, michael@0: nsHTMLReflowMetrics& aDesiredStretchSize) = 0; michael@0: michael@0: /* Get the mEmbellishData member variable. */ michael@0: michael@0: NS_IMETHOD michael@0: GetEmbellishData(nsEmbellishData& aEmbellishData) = 0; michael@0: michael@0: michael@0: /* SUPPORT FOR SCRIPTING ELEMENTS */ michael@0: /*====================================================================*/ michael@0: michael@0: /* Get the mPresentationData member variable. */ michael@0: michael@0: NS_IMETHOD michael@0: GetPresentationData(nsPresentationData& aPresentationData) = 0; michael@0: michael@0: /* InheritAutomaticData() / TransmitAutomaticData() : michael@0: * There are precise rules governing each MathML frame and its children. michael@0: * Properties such as the scriptlevel or the embellished nature of a frame michael@0: * depend on those rules. Also, certain properties that we use to emulate michael@0: * TeX rendering rules are frame-dependent too. These two methods are meant michael@0: * to be implemented by frame classes that need to assert specific properties michael@0: * within their subtrees. michael@0: * michael@0: * InheritAutomaticData() is called in a top-down manner [like nsIFrame::Init], michael@0: * as we descend the frame tree, whereas TransmitAutomaticData() is called in a michael@0: * bottom-up manner, as we ascend the tree [like nsIFrame::SetInitialChildList]. michael@0: * However, unlike Init() and SetInitialChildList() which are called only once michael@0: * during the life-time of a frame (when initially constructing the frame tree), michael@0: * these two methods are called to build automatic data after the ... michael@0: * subtree has been constructed fully, and are called again as we walk a child's michael@0: * subtree to handle dynamic changes that happen in the content model. michael@0: * michael@0: * As a rule of thumb: michael@0: * michael@0: * 1. Use InheritAutomaticData() to set properties related to your ancestors: michael@0: * - set properties that are intrinsic to yourself michael@0: * - set properties that depend on the state that you expect your ancestors michael@0: * to have already reached in their own InheritAutomaticData(). michael@0: * - set properties that your descendants assume that you would have set in michael@0: * your InheritAutomaticData() -- this way, they can safely query them and michael@0: * the process will feed upon itself. michael@0: * michael@0: * 2. Use TransmitAutomaticData() to set properties related to your descendants: michael@0: * - set properties that depend on the state that you expect your descendants michael@0: * to have reached upon processing their own TransmitAutomaticData(). michael@0: * - transmit properties that your descendants expect that you will transmit to michael@0: * them in your TransmitAutomaticData() -- this way, they remain up-to-date. michael@0: * - set properties that your ancestors expect that you would set in your michael@0: * TransmitAutomaticData() -- this way, they can safely query them and the michael@0: * process will feed upon itself. michael@0: */ michael@0: michael@0: NS_IMETHOD michael@0: InheritAutomaticData(nsIFrame* aParent) = 0; michael@0: michael@0: NS_IMETHOD michael@0: TransmitAutomaticData() = 0; michael@0: michael@0: /* UpdatePresentationData: michael@0: * Updates the frame's compression flag. michael@0: * A frame becomes "compressed" (or "cramped") according to TeX rendering michael@0: * rules (TeXBook, Ch.17, p.140-141). michael@0: * michael@0: * @param aFlagsValues [in] michael@0: * The new values (e.g., compress) that are going to be michael@0: * updated. michael@0: * michael@0: * @param aWhichFlags [in] michael@0: * The flags that are relevant to this call. Since not all calls michael@0: * are meant to update all flags at once, aWhichFlags is used michael@0: * to distinguish flags that need to retain their existing values michael@0: * from flags that need to be turned on (or turned off). If a bit michael@0: * is set in aWhichFlags, then the corresponding value (which michael@0: * can be 0 or 1) is taken from aFlagsValues and applied to the michael@0: * frame. Therefore, by setting their bits in aWhichFlags, and michael@0: * setting their desired values in aFlagsValues, it is possible to michael@0: * update some flags in the frame, leaving the other flags unchanged. michael@0: */ michael@0: NS_IMETHOD michael@0: UpdatePresentationData(uint32_t aFlagsValues, michael@0: uint32_t aWhichFlags) = 0; michael@0: michael@0: /* UpdatePresentationDataFromChildAt : michael@0: * Sets compression flag on the whole tree. For child frames michael@0: * at aFirstIndex up to aLastIndex, this method sets their michael@0: * compression flags. The update is propagated down the subtrees of each of michael@0: * these child frames. michael@0: * michael@0: * @param aFirstIndex [in] michael@0: * Index of the first child from where the update is propagated. michael@0: * michael@0: * @param aLastIndex [in] michael@0: * Index of the last child where to stop the update. michael@0: * A value of -1 means up to last existing child. michael@0: * michael@0: * @param aFlagsValues [in] michael@0: * The new values (e.g., compress) that are going to be michael@0: * assigned in the whole sub-trees. michael@0: * michael@0: * @param aWhichFlags [in] michael@0: * The flags that are relevant to this call. See UpdatePresentationData() michael@0: * for more details about this parameter. 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 aWhichFlags) = 0; michael@0: michael@0: // If aFrame is a child frame, returns the script increment which this frame michael@0: // imposes on the specified frame, ignoring any artificial adjustments to michael@0: // scriptlevel. michael@0: // Returns 0 if the specified frame isn't a child frame. michael@0: virtual uint8_t michael@0: ScriptIncrement(nsIFrame* aFrame) = 0; michael@0: michael@0: // Returns true if the frame is considered to be an mrow for layout purposes. michael@0: // This includes inferred mrows, but excludes elements with a single michael@0: // child. In the latter case, the child is to be treated as if it wasn't michael@0: // within an mrow, so we pretend the mrow isn't mrow-like. michael@0: virtual bool michael@0: IsMrowLike() = 0; michael@0: }; michael@0: michael@0: // struct used by a container frame to keep track of its embellishments. michael@0: // By convention, the data that we keep here is bubbled from the embellished michael@0: // hierarchy, and it remains unchanged unless we have to recover from a change michael@0: // that occurs in the embellished hierarchy. The struct remains in its nil michael@0: // state in those frames that are not part of the embellished hierarchy. michael@0: struct nsEmbellishData { michael@0: // bits used to mark certain properties of our embellishments michael@0: uint32_t flags; michael@0: michael@0: // pointer on the frame at the core of the embellished hierarchy michael@0: nsIFrame* coreFrame; michael@0: michael@0: // stretchy direction that the nsMathMLChar owned by the core supports michael@0: nsStretchDirection direction; michael@0: michael@0: // spacing that may come from depending on its 'form'. Since michael@0: // the 'form' may also depend on the position of the outermost michael@0: // embellished ancestor, the set up of these values may require michael@0: // looking up the position of our ancestors. michael@0: nscoord leadingSpace; michael@0: nscoord trailingSpace; michael@0: michael@0: nsEmbellishData() { michael@0: flags = 0; michael@0: coreFrame = nullptr; michael@0: direction = NS_STRETCH_DIRECTION_UNSUPPORTED; michael@0: leadingSpace = 0; michael@0: trailingSpace = 0; michael@0: } michael@0: }; michael@0: michael@0: // struct used by a container frame to modulate its presentation. michael@0: // By convention, the data that we keep in this struct can change depending michael@0: // on any of our ancestors and/or descendants. If a data can be resolved michael@0: // solely from the embellished hierarchy, and it remains immutable once michael@0: // resolved, we put it in |nsEmbellishData|. If it can be affected by other michael@0: // things, it comes here. This struct is updated as we receive information michael@0: // transmitted by our ancestors and is kept in sync with changes in our michael@0: // descendants that affects us. michael@0: struct nsPresentationData { michael@0: // bits for: compressed, etc michael@0: uint32_t flags; michael@0: michael@0: // handy pointer on our base child (the 'nucleus' in TeX), but it may be michael@0: // null here (e.g., tags like , , , etc, won't michael@0: // pick a particular child in their child list to be the base) michael@0: nsIFrame* baseFrame; michael@0: michael@0: nsPresentationData() { michael@0: flags = 0; michael@0: baseFrame = nullptr; michael@0: } michael@0: }; michael@0: michael@0: // ========================================================================== michael@0: // Bits used for the presentation flags -- these bits are set michael@0: // in their relevant situation as they become available michael@0: michael@0: // This bit is used to emulate TeX rendering. michael@0: // Internal use only, cannot be set by the user with an attribute. michael@0: #define NS_MATHML_COMPRESSED 0x00000002U michael@0: michael@0: // This bit is set if the frame will fire a vertical stretch michael@0: // command on all its (non-empty) children. michael@0: // Tags like (or an inferred mrow), mpadded, etc, will fire a michael@0: // vertical stretch command on all their non-empty children michael@0: #define NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY 0x00000004U michael@0: michael@0: // This bit is set if the frame will fire a horizontal stretch michael@0: // command on all its (non-empty) children. michael@0: // Tags like munder, mover, munderover, will fire a michael@0: // horizontal stretch command on all their non-empty children michael@0: #define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY 0x00000008U michael@0: michael@0: // This bit is set if the frame is "space-like", as defined by the spec. michael@0: #define NS_MATHML_SPACE_LIKE 0x00000040U michael@0: michael@0: // This bit is set when the frame cannot be formatted due to an michael@0: // error (e.g., invalid markup such as a without an overscript). michael@0: // When set, a visual feedback will be provided to the user. michael@0: #define NS_MATHML_ERROR 0x80000000U michael@0: michael@0: // a bit used for debug michael@0: #define NS_MATHML_STRETCH_DONE 0x20000000U michael@0: michael@0: // This bit is used for visual debug. When set, the bounding box michael@0: // of your frame is painted. This visual debug enable to ensure that michael@0: // you have properly filled your mReference and mBoundingMetrics in michael@0: // Place(). michael@0: #define NS_MATHML_SHOW_BOUNDING_METRICS 0x10000000U michael@0: michael@0: // Macros that retrieve those bits michael@0: michael@0: #define NS_MATHML_IS_COMPRESSED(_flags) \ michael@0: (NS_MATHML_COMPRESSED == ((_flags) & NS_MATHML_COMPRESSED)) michael@0: michael@0: #define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(_flags) \ michael@0: (NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY)) michael@0: michael@0: #define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(_flags) \ michael@0: (NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY)) michael@0: michael@0: #define NS_MATHML_IS_SPACE_LIKE(_flags) \ michael@0: (NS_MATHML_SPACE_LIKE == ((_flags) & NS_MATHML_SPACE_LIKE)) michael@0: michael@0: #define NS_MATHML_HAS_ERROR(_flags) \ michael@0: (NS_MATHML_ERROR == ((_flags) & NS_MATHML_ERROR)) michael@0: michael@0: #define NS_MATHML_STRETCH_WAS_DONE(_flags) \ michael@0: (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE)) michael@0: michael@0: #define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \ michael@0: (NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS)) michael@0: michael@0: // ========================================================================== michael@0: // Bits used for the embellish flags -- these bits are set michael@0: // in their relevant situation as they become available michael@0: michael@0: // This bit is set if the frame is an embellished operator. michael@0: #define NS_MATHML_EMBELLISH_OPERATOR 0x00000001 michael@0: michael@0: // This bit is set if the frame is an frame or an embellihsed michael@0: // operator for which the core has movablelimits="true" michael@0: #define NS_MATHML_EMBELLISH_MOVABLELIMITS 0x00000002 michael@0: michael@0: // This bit is set if the frame is an frame or an embellihsed michael@0: // operator for which the core has accent="true" michael@0: #define NS_MATHML_EMBELLISH_ACCENT 0x00000004 michael@0: michael@0: // This bit is set if the frame is an or with michael@0: // an accent frame michael@0: #define NS_MATHML_EMBELLISH_ACCENTOVER 0x00000008 michael@0: michael@0: // This bit is set if the frame is an or with michael@0: // an accentunder frame michael@0: #define NS_MATHML_EMBELLISH_ACCENTUNDER 0x00000010 michael@0: michael@0: // Macros that retrieve those bits michael@0: michael@0: #define NS_MATHML_IS_EMBELLISH_OPERATOR(_flags) \ michael@0: (NS_MATHML_EMBELLISH_OPERATOR == ((_flags) & NS_MATHML_EMBELLISH_OPERATOR)) michael@0: michael@0: #define NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(_flags) \ michael@0: (NS_MATHML_EMBELLISH_MOVABLELIMITS == ((_flags) & NS_MATHML_EMBELLISH_MOVABLELIMITS)) michael@0: michael@0: #define NS_MATHML_EMBELLISH_IS_ACCENT(_flags) \ michael@0: (NS_MATHML_EMBELLISH_ACCENT == ((_flags) & NS_MATHML_EMBELLISH_ACCENT)) michael@0: michael@0: #define NS_MATHML_EMBELLISH_IS_ACCENTOVER(_flags) \ michael@0: (NS_MATHML_EMBELLISH_ACCENTOVER == ((_flags) & NS_MATHML_EMBELLISH_ACCENTOVER)) michael@0: michael@0: #define NS_MATHML_EMBELLISH_IS_ACCENTUNDER(_flags) \ michael@0: (NS_MATHML_EMBELLISH_ACCENTUNDER == ((_flags) & NS_MATHML_EMBELLISH_ACCENTUNDER)) michael@0: michael@0: #endif /* nsIMathMLFrame_h___ */