1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla MathML Project.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * The University Of Queensland.
19 : * Portions created by the Initial Developer are Copyright (C) 1999
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Roger B. Sidje <rbs@maths.uq.edu.au>
24 : * Shyjan Mahamud <mahamud@cs.cmu.edu>
25 : * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
26 : * Frederic Wang <fred.wang@free.fr>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either of the GNU General Public License Version 2 or later (the "GPL"),
30 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : #ifndef nsMathMLChar_h___
43 : #define nsMathMLChar_h___
44 :
45 : #include "nsMathMLOperators.h"
46 : #include "nsMathMLFrame.h"
47 :
48 : class nsGlyphTable;
49 :
50 : // Hints for Stretch() to indicate criteria for stretching
51 : enum {
52 : // Don't stretch
53 : NS_STRETCH_NONE = 0x00,
54 : // Variable size stretches
55 : NS_STRETCH_VARIABLE_MASK = 0x0F,
56 : NS_STRETCH_NORMAL = 0x01, // try to stretch to requested size
57 : NS_STRETCH_NEARER = 0x02, // stretch very close to requested size
58 : NS_STRETCH_SMALLER = 0x04, // don't stretch more than requested size
59 : NS_STRETCH_LARGER = 0x08, // don't stretch less than requested size
60 : // A largeop in displaystyle
61 : NS_STRETCH_LARGEOP = 0x10,
62 : NS_STRETCH_INTEGRAL = 0x20,
63 :
64 : // Intended for internal use:
65 : // Find the widest metrics that might be returned from a vertical stretch
66 : NS_STRETCH_MAXWIDTH = 0x40
67 : };
68 :
69 : // A single glyph in our internal representation is characterized by a 'code@font'
70 : // pair. The 'code' is interpreted as a Unicode point or as the direct glyph index
71 : // (depending on the type of nsGlyphTable where this comes from). The 'font' is a
72 : // numeric identifier given to the font to which the glyph belongs.
73 : struct nsGlyphCode {
74 : PRUnichar code[2];
75 : PRInt32 font;
76 :
77 0 : PRInt32 Length() { return (code[1] == PRUnichar('\0') ? 1 : 2); }
78 0 : bool Exists() const
79 : {
80 0 : return (code[0] != 0);
81 : }
82 0 : bool operator==(const nsGlyphCode& other) const
83 : {
84 0 : return (other.code[0] == code[0] && other.code[1] == code[1] &&
85 0 : other.font == font);
86 : }
87 0 : bool operator!=(const nsGlyphCode& other) const
88 : {
89 0 : return ! operator==(other);
90 : }
91 : };
92 :
93 : // Class used to handle stretchy symbols (accent, delimiter and boundary symbols).
94 : // There are composite characters that need to be built recursively from other
95 : // characters. Since these are rare we use a light-weight mechanism to handle
96 : // them. Specifically, as need arises we append a singly-linked list of child
97 : // chars with their mParent pointing to the first element in the list, except in
98 : // the originating first element itself where it points to null. mSibling points
99 : // to the next element in the list. Since the originating first element is the
100 : // parent of the others, we call it the "root" char of the list. Testing !mParent
101 : // tells whether you are that "root" during the recursion. The parent delegates
102 : // most of the tasks to the children.
103 : class nsMathMLChar
104 : {
105 : public:
106 : // constructor and destructor
107 0 : nsMathMLChar(nsMathMLChar* aParent = nsnull) {
108 0 : MOZ_COUNT_CTOR(nsMathMLChar);
109 0 : mStyleContext = nsnull;
110 0 : mSibling = nsnull;
111 0 : mParent = aParent;
112 0 : mUnscaledAscent = 0;
113 0 : mScaleX = mScaleY = 1.0;
114 0 : mDrawNormal = true;
115 0 : mMirrored = false;
116 0 : }
117 :
118 0 : ~nsMathMLChar() { // not a virtual destructor: this class is not intended to be subclassed
119 0 : MOZ_COUNT_DTOR(nsMathMLChar);
120 : // there is only one style context owned by the "root" char
121 : // and it may be used by child chars as well
122 0 : if (!mParent && mStyleContext) { // only the "root" need to release it
123 0 : mStyleContext->Release();
124 : }
125 0 : if (mSibling) {
126 0 : delete mSibling;
127 : }
128 0 : }
129 :
130 : nsresult
131 : Display(nsDisplayListBuilder* aBuilder,
132 : nsIFrame* aForFrame,
133 : const nsDisplayListSet& aLists,
134 : const nsRect* aSelectedRect = nsnull);
135 :
136 : void PaintForeground(nsPresContext* aPresContext,
137 : nsRenderingContext& aRenderingContext,
138 : nsPoint aPt,
139 : bool aIsSelected);
140 :
141 : // This is the method called to ask the char to stretch itself.
142 : // @param aContainerSize - IN - suggested size for the stretched char
143 : // @param aDesiredStretchSize - OUT - the size that the char wants
144 : nsresult
145 : Stretch(nsPresContext* aPresContext,
146 : nsRenderingContext& aRenderingContext,
147 : nsStretchDirection aStretchDirection,
148 : const nsBoundingMetrics& aContainerSize,
149 : nsBoundingMetrics& aDesiredStretchSize,
150 : PRUint32 aStretchHint,
151 : bool aRTL);
152 :
153 : void
154 : SetData(nsPresContext* aPresContext,
155 : nsString& aData);
156 :
157 : void
158 0 : GetData(nsString& aData) {
159 0 : aData = mData;
160 0 : }
161 :
162 : PRInt32
163 0 : Length() {
164 0 : return mData.Length();
165 : }
166 :
167 : nsStretchDirection
168 0 : GetStretchDirection() {
169 0 : return mDirection;
170 : }
171 :
172 : // Sometimes we only want to pass the data to another routine,
173 : // this function helps to avoid copying
174 : const PRUnichar*
175 : get() {
176 : return mData.get();
177 : }
178 :
179 : void
180 0 : GetRect(nsRect& aRect) {
181 0 : aRect = mRect;
182 0 : }
183 :
184 : void
185 0 : SetRect(const nsRect& aRect) {
186 0 : mRect = aRect;
187 : // shift the orgins of child chars if any
188 0 : if (!mParent && mSibling) { // only a "root" having child chars can enter here
189 0 : for (nsMathMLChar* child = mSibling; child; child = child->mSibling) {
190 0 : nsRect rect;
191 0 : child->GetRect(rect);
192 0 : rect.MoveBy(mRect.x, mRect.y);
193 0 : child->SetRect(rect);
194 : }
195 : }
196 0 : }
197 :
198 : // Get the maximum width that the character might have after a vertical
199 : // Stretch().
200 : //
201 : // @param aStretchHint can be the value that will be passed to Stretch().
202 : // It is used to determine whether the operator is stretchy or a largeop.
203 : // @param aMaxSize is the value of the "maxsize" attribute.
204 : // @param aMaxSizeIsAbsolute indicates whether the aMaxSize is an absolute
205 : // value in app units (true) or a multiplier of the base size (false).
206 : nscoord
207 : GetMaxWidth(nsPresContext* aPresContext,
208 : nsRenderingContext& aRenderingContext,
209 : PRUint32 aStretchHint = NS_STRETCH_NORMAL,
210 : float aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
211 : // Perhaps just nsOperatorFlags aFlags.
212 : // But need DisplayStyle for largeOp,
213 : // or remove the largeop bit from flags.
214 : bool aMaxSizeIsAbsolute = false);
215 :
216 : // Metrics that _exactly_ enclose the char. The char *must* have *already*
217 : // being stretched before you can call the GetBoundingMetrics() method.
218 : // IMPORTANT: since chars have their own style contexts, and may be rendered
219 : // with glyphs that are not in the parent font, just calling the default
220 : // aRenderingContext.GetBoundingMetrics(aChar) can give incorrect results.
221 : void
222 0 : GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) {
223 0 : aBoundingMetrics = mBoundingMetrics;
224 0 : }
225 :
226 : void
227 0 : SetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) {
228 0 : mBoundingMetrics = aBoundingMetrics;
229 0 : }
230 :
231 : // Hooks to access the extra leaf style contexts given to the MathMLChars.
232 : // They provide an interface to make them accessible to the Style System via
233 : // the Get/Set AdditionalStyleContext() APIs. Owners of MathMLChars
234 : // should honor these APIs.
235 : nsStyleContext* GetStyleContext() const;
236 :
237 : void SetStyleContext(nsStyleContext* aStyleContext);
238 :
239 : protected:
240 : friend class nsGlyphTable;
241 : nsString mData;
242 :
243 : // support for handling composite stretchy chars like TeX over/under braces
244 : nsMathMLChar* mSibling;
245 : nsMathMLChar* mParent;
246 :
247 : private:
248 : nsRect mRect;
249 : nsStretchDirection mDirection;
250 : nsBoundingMetrics mBoundingMetrics;
251 : nsStyleContext* mStyleContext;
252 : nsGlyphTable* mGlyphTable;
253 : nsGlyphCode mGlyph;
254 : // mFamily is non-empty when the family for the current size is different
255 : // from the family in the nsStyleContext.
256 : nsString mFamily;
257 : // mUnscaledAscent is the actual ascent of the char.
258 : nscoord mUnscaledAscent;
259 : // mScaleX, mScaleY are the factors by which we scale the char.
260 : float mScaleX, mScaleY;
261 : // mDrawNormal indicates whether we use special glyphs or not.
262 : bool mDrawNormal;
263 : // mMirrored indicates whether the character is mirrored.
264 : bool mMirrored;
265 :
266 : class StretchEnumContext;
267 : friend class StretchEnumContext;
268 :
269 : // helper methods
270 : nsresult
271 : StretchInternal(nsPresContext* aPresContext,
272 : nsRenderingContext& aRenderingContext,
273 : nsStretchDirection& aStretchDirection,
274 : const nsBoundingMetrics& aContainerSize,
275 : nsBoundingMetrics& aDesiredStretchSize,
276 : PRUint32 aStretchHint,
277 : float aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
278 : bool aMaxSizeIsAbsolute = false);
279 :
280 : nsresult
281 : ComposeChildren(nsPresContext* aPresContext,
282 : nsRenderingContext& aRenderingContext,
283 : nsGlyphTable* aGlyphTable,
284 : nscoord aTargetSize,
285 : nsBoundingMetrics& aCompositeSize,
286 : PRUint32 aStretchHint);
287 :
288 : nsresult
289 : PaintVertically(nsPresContext* aPresContext,
290 : nsRenderingContext& aRenderingContext,
291 : nsFont& aFont,
292 : nsStyleContext* aStyleContext,
293 : nsGlyphTable* aGlyphTable,
294 : nsRect& aRect);
295 :
296 : nsresult
297 : PaintHorizontally(nsPresContext* aPresContext,
298 : nsRenderingContext& aRenderingContext,
299 : nsFont& aFont,
300 : nsStyleContext* aStyleContext,
301 : nsGlyphTable* aGlyphTable,
302 : nsRect& aRect);
303 :
304 : void
305 : ApplyTransforms(nsRenderingContext& aRenderingContext, nsRect &r);
306 : };
307 :
308 : #endif /* nsMathMLChar_h___ */
|