Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / base / nsBidiPresUtils.h
blob27ff04804b534cc9230ded80703aa350c91b09f2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * IBM Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2000
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * IBM Corporation
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifdef IBMBIDI
42 #ifndef nsBidiPresUtils_h___
43 #define nsBidiPresUtils_h___
45 #include "nsVoidArray.h"
46 #include "nsIFrame.h"
47 #include "nsBidi.h"
48 #include "nsBidiUtils.h"
49 #include "nsCOMPtr.h"
50 #include "nsDataHashtable.h"
51 #include "nsBlockFrame.h"
52 #include "nsTHashtable.h"
54 /**
55 * A structure representing some continuation state for each frame on the line,
56 * used to determine the first and the last continuation frame for each
57 * continuation chain on the line.
59 struct nsFrameContinuationState : public nsVoidPtrHashKey
61 nsFrameContinuationState(const void *aFrame) : nsVoidPtrHashKey(aFrame) {}
63 /**
64 * The first visual frame in the continuation chain containing this frame, or
65 * nsnull if this frame is the first visual frame in the chain.
67 nsIFrame* mFirstVisualFrame;
69 /**
70 * The number of frames in the continuation chain containing this frame, if
71 * this frame is the first visual frame of the chain, or 0 otherwise.
73 PRUint32 mFrameCount;
75 /**
76 * TRUE if this frame is the first visual frame of its continuation chain on
77 * this line and the chain has some frames on the previous lines.
79 PRPackedBool mHasContOnPrevLines;
81 /**
82 * TRUE if this frame is the first visual frame of its continuation chain on
83 * this line and the chain has some frames left for next lines.
85 PRPackedBool mHasContOnNextLines;
89 * Following type is used to pass needed hashtable to reordering methods
91 typedef nsTHashtable<nsFrameContinuationState> nsContinuationStates;
93 /**
94 * A structure representing a logical position which should be resolved
95 * into its visual position during BiDi processing.
97 struct nsBidiPositionResolve
99 // [in] Logical index within string.
100 PRInt32 logicalIndex;
101 // [out] Visual index within string.
102 // If the logical position was not found, set to kNotFound.
103 PRInt32 visualIndex;
104 // [out] Visual position of the character, from the left (on the X axis), in twips.
105 // Eessentially, this is the X position (relative to the rendering context) where the text was drawn + the font metric of the visual string to the left of the given logical position.
106 // If the logical position was not found, set to kNotFound.
107 PRInt32 visualLeftTwips;
110 class nsBidiPresUtils {
111 public:
112 nsBidiPresUtils();
113 ~nsBidiPresUtils();
114 PRBool IsSuccessful(void) const;
117 * Interface for the processor used by ProcessText. Used by process text to
118 * collect information about the width of subruns and to notify where each
119 * subrun should be rendered.
121 class BidiProcessor {
122 public:
123 virtual ~BidiProcessor() { }
126 * Sets the current text with the given length and the given direction.
128 * @remark The reason that the function gives a string instead of an index
129 * is that ProcessText copies and modifies the string passed to it, so
130 * passing an index would be impossible.
132 * @param aText The string of text.
133 * @param aLength The length of the string of text.
134 * @param aDirection The direction of the text. The string will never have
135 * mixed direction.
137 virtual void SetText(const PRUnichar* aText,
138 PRInt32 aLength,
139 nsBidiDirection aDirection) = 0;
142 * Returns the measured width of the text given in SetText. If SetText was
143 * not called with valid parameters, the result of this call is undefined.
144 * This call is guaranteed to only be called once between SetText calls.
145 * Will be invoked before DrawText.
147 virtual nscoord GetWidth() = 0;
150 * Draws the text given in SetText to a rendering context. If SetText was
151 * not called with valid parameters, the result of this call is undefined.
152 * This call is guaranteed to only be called once between SetText calls.
154 * @param aXOffset The offset of the left side of the substring to be drawn
155 * from the beginning of the overall string passed to ProcessText.
156 * @param aWidth The width returned by GetWidth.
158 virtual void DrawText(nscoord aXOffset,
159 nscoord aWidth) = 0;
163 * Make Bidi engine calculate the embedding levels of the frames that are
164 * descendants of a given block frame.
166 * @param aBlockFrame The block frame
167 * @param aIsVisualFormControl [IN] Set if we are in a form control on a
168 * visual page.
169 * @see nsBlockFrame::IsVisualFormControl
171 * @lina 06/18/2000
173 nsresult Resolve(nsBlockFrame* aBlockFrame,
174 PRBool aIsVisualFormControl);
177 * Reorder this line using Bidi engine.
178 * Update frame array, following the new visual sequence.
180 * @lina 05/02/2000
182 void ReorderFrames(nsIFrame* aFirstFrameOnLine,
183 PRInt32 aNumFramesOnLine);
186 * Format Unicode text, taking into account bidi capabilities
187 * of the platform. The formatting includes: reordering, Arabic shaping,
188 * symmetric and numeric swapping, removing control characters.
190 * @lina 06/18/2000
192 nsresult FormatUnicodeText(nsPresContext* aPresContext,
193 PRUnichar* aText,
194 PRInt32& aTextLength,
195 nsCharType aCharType,
196 PRBool aIsOddLevel);
199 * Return our nsBidi object (bidi reordering engine)
201 nsresult GetBidiEngine(nsBidi** aBidiEngine);
204 * Reorder plain text using the Unicode Bidi algorithm and send it to
205 * a rendering context for rendering.
207 * @param[in] aText the string to be rendered (in logical order)
208 * @param aLength the number of characters in the string
209 * @param aBaseDirection the base direction of the string
210 * NSBIDI_LTR - left-to-right string
211 * NSBIDI_RTL - right-to-left string
212 * @param aPresContext the presentation context
213 * @param aRenderingContext the rendering context
214 * @param aX the x-coordinate to render the string
215 * @param aY the y-coordinate to render the string
216 * @param[in,out] aPosResolve array of logical positions to resolve into visual positions; can be nsnull if this functionality is not required
217 * @param aPosResolveCount number of items in the aPosResolve array
219 nsresult RenderText(const PRUnichar* aText,
220 PRInt32 aLength,
221 nsBidiDirection aBaseDirection,
222 nsPresContext* aPresContext,
223 nsIRenderingContext& aRenderingContext,
224 nscoord aX,
225 nscoord aY,
226 nsBidiPositionResolve* aPosResolve = nsnull,
227 PRInt32 aPosResolveCount = 0)
229 return ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext, aRenderingContext,
230 MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nsnull);
233 nscoord MeasureTextWidth(const PRUnichar* aText,
234 PRInt32 aLength,
235 nsBidiDirection aBaseDirection,
236 nsPresContext* aPresContext,
237 nsIRenderingContext& aRenderingContext)
239 nscoord length;
240 nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext, aRenderingContext,
241 MODE_MEASURE, 0, 0, nsnull, 0, &length);
242 return NS_SUCCEEDED(rv) ? length : 0;
246 * Check if a line is reordered, i.e., if the child frames are not
247 * all laid out left-to-right.
248 * @param aFirstFrameOnLine : first frame of the line to be tested
249 * @param aNumFramesOnLine : number of frames on this line
250 * @param[out] aLeftMost : leftmost frame on this line
251 * @param[out] aRightMost : rightmost frame on this line
253 PRBool CheckLineOrder(nsIFrame* aFirstFrameOnLine,
254 PRInt32 aNumFramesOnLine,
255 nsIFrame** aLeftmost,
256 nsIFrame** aRightmost);
259 * Get the frame to the right of the given frame, on the same line.
260 * @param aFrame : We're looking for the frame to the right of this frame.
261 * If null, return the leftmost frame on the line.
262 * @param aFirstFrameOnLine : first frame of the line to be tested
263 * @param aNumFramesOnLine : number of frames on this line
265 nsIFrame* GetFrameToRightOf(const nsIFrame* aFrame,
266 nsIFrame* aFirstFrameOnLine,
267 PRInt32 aNumFramesOnLine);
270 * Get the frame to the left of the given frame, on the same line.
271 * @param aFrame : We're looking for the frame to the left of this frame.
272 * If null, return the rightmost frame on the line.
273 * @param aFirstFrameOnLine : first frame of the line to be tested
274 * @param aNumFramesOnLine : number of frames on this line
276 nsIFrame* GetFrameToLeftOf(const nsIFrame* aFrame,
277 nsIFrame* aFirstFrameOnLine,
278 PRInt32 aNumFramesOnLine);
281 * Get the bidi embedding level of the given (inline) frame.
283 static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame);
286 * Get the bidi base level of the given (inline) frame.
288 static nsBidiLevel GetFrameBaseLevel(nsIFrame* aFrame);
290 enum Mode { MODE_DRAW, MODE_MEASURE };
293 * Reorder plain text using the Unicode Bidi algorithm and send it to
294 * a processor for rendering or measuring
296 * @param[in] aText the string to be processed (in logical order)
297 * @param aLength the number of characters in the string
298 * @param aBaseDirection the base direction of the string
299 * NSBIDI_LTR - left-to-right string
300 * NSBIDI_RTL - right-to-left string
301 * @param aPresContext the presentation context
302 * @param aprocessor the bidi processor
303 * @param aMode the operation to process
304 * MODE_DRAW - invokes DrawText on the processor for each substring
305 * MODE_MEASURE - does not invoke DrawText on the processor
306 * Note that the string is always measured, regardless of mode
307 * @param[in,out] aPosResolve array of logical positions to resolve into
308 * visual positions; can be nsnull if this functionality is not required
309 * @param aPosResolveCount number of items in the aPosResolve array
310 * @param[out] aWidth Pointer to where the width will be stored (may be null)
312 nsresult ProcessText(const PRUnichar* aText,
313 PRInt32 aLength,
314 nsBidiDirection aBaseDirection,
315 nsPresContext* aPresContext,
316 BidiProcessor& aprocessor,
317 Mode aMode,
318 nsBidiPositionResolve* aPosResolve,
319 PRInt32 aPosResolveCount,
320 nscoord* aWidth);
322 private:
323 nsresult ProcessTextForRenderingContext(const PRUnichar* aText,
324 PRInt32 aLength,
325 nsBidiDirection aBaseDirection,
326 nsPresContext* aPresContext,
327 nsIRenderingContext& aRenderingContext,
328 Mode aMode,
329 nscoord aX, // DRAW only
330 nscoord aY, // DRAW only
331 nsBidiPositionResolve* aPosResolve, /* may be null */
332 PRInt32 aPosResolveCount,
333 nscoord* aWidth /* may be null */);
336 * Create a string containing entire text content of this block.
338 * @lina 05/02/2000
340 void CreateBlockBuffer();
343 * Set up an array of the frames after splitting frames so that each frame has
344 * consistent directionality. At this point the frames are still in logical
345 * order
347 void InitLogicalArray(nsIFrame* aCurrentFrame);
350 * Initialize the logically-ordered array of frames
351 * using the top-level frames of a single line
353 void InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine,
354 PRInt32 aNumFramesOnLine);
357 * Reorder the frame array from logical to visual order
359 * @param aReordered TRUE on return if the visual order is different from
360 * the logical order
361 * @param aHasRTLFrames TRUE on return if at least one of the frames is RTL
362 * (and therefore might have reordered descendents)
364 nsresult Reorder(PRBool& aReordered, PRBool& aHasRTLFrames);
367 * Position aFrame and it's descendants to their visual places. Also if aFrame
368 * is not leaf, resize it to embrace it's children.
370 * @param aFrame The frame which itself and its children are going
371 * to be repositioned
372 * @param aIsOddLevel TRUE means the embedding level of this frame is odd
373 * @param[in,out] aLeft IN value is the starting position of aFrame(without
374 * considering its left margin)
375 * OUT value will be the ending position of aFrame(after
376 * adding its right margin)
377 * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
379 void RepositionFrame(nsIFrame* aFrame,
380 PRBool aIsOddLevel,
381 nscoord& aLeft,
382 nsContinuationStates* aContinuationStates) const;
385 * Initialize the continuation state(nsFrameContinuationState) to
386 * (nsnull, 0) for aFrame and its descendants.
388 * @param aFrame The frame which itself and its descendants will
389 * be initialized
390 * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
392 void InitContinuationStates(nsIFrame* aFrame,
393 nsContinuationStates* aContinuationStates) const;
396 * Determine if aFrame is leftmost or rightmost, and set aIsLeftMost and
397 * aIsRightMost values. Also set continuation states of aContinuationStates.
399 * A frame is leftmost if it's the first appearance of its continuation chain
400 * on the line and the chain is on its first line if it's LTR or the chain is
401 * on its last line if it's RTL.
402 * A frame is rightmost if it's the last appearance of its continuation chain
403 * on the line and the chain is on its first line if it's RTL or the chain is
404 * on its last line if it's LTR.
406 * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
407 * @param[out] aIsLeftMost TRUE means aFrame is leftmost frame or continuation
408 * @param[out] aIsRightMost TRUE means aFrame is rightmost frame or continuation
410 void IsLeftOrRightMost(nsIFrame* aFrame,
411 nsContinuationStates* aContinuationStates,
412 PRBool& aIsLeftMost /* out */,
413 PRBool& aIsRightMost /* out */) const;
416 * Adjust frame positions following their visual order
418 * @param aFirstChild the first kid
420 * @lina 04/11/2000
422 void RepositionInlineFrames(nsIFrame* aFirstChild) const;
425 * Helper method for Resolve()
426 * Truncate a text frame to the end of a single-directional run and possibly
427 * create a continuation frame for the remainder of its content.
429 * @param aFrame the original frame
430 * @param aNewFrame [OUT] the new frame that was created
431 * @param aFrameIndex [IN/OUT] index of aFrame in mLogicalFrames
432 * @param aStart [IN] the start of the content mapped by aFrame (and
433 * any fluid continuations)
434 * @param aEnd [IN] the offset of the end of the single-directional
435 * text run.
436 * @param aLineNeedsUpdate [OUT] set to true if we're re-using a frame (which
437 * might be on another line).
439 * If there is already a bidi continuation for this frame in mLogicalFrames,
440 * no new frame will be created. On exit aNewFrame will point to the existing
441 * bidi continuation and aFrameIndex will contain its index.
443 * If aFrame has fluid continuations (which can happen when re-resolving
444 * after line breaking) all the frames in the continuation chain except for
445 * the last one will be set to zero length and the last one will be truncated
446 * at aEnd.
448 * aFrame must always be a first-in-flow.
450 * @see Resolve()
451 * @see RemoveBidiContinuation()
453 PRBool EnsureBidiContinuation(nsIFrame* aFrame,
454 nsIFrame** aNewFrame,
455 PRInt32& aFrameIndex,
456 PRInt32 aStart,
457 PRInt32 aEnd,
458 PRBool& aLineNeedsUpdate);
461 * Helper method for Resolve()
462 * Convert one or more bidi continuation frames created in a previous reflow by
463 * EnsureBidiContinuation() into fluid continuations.
464 * @param aFrame the frame whose continuations are to be removed
465 * @param aFirstIndex index of aFrame in mLogicalFrames
466 * @param aLastIndex index of the last frame to be removed
467 * @param aOffset [OUT] count of directional frames removed. Since
468 * directional frames have control characters
469 * corresponding to them in mBuffer, the pointers to
470 * mBuffer in Resolve() will need to be updated after
471 * deleting the frames.
473 * @see Resolve()
474 * @see EnsureBidiContinuation()
476 void RemoveBidiContinuation(nsIFrame* aFrame,
477 PRInt32 aFirstIndex,
478 PRInt32 aLastIndex,
479 PRInt32& aOffset) const;
480 void CalculateCharType(PRInt32& aOffset,
481 PRInt32 aCharTypeLimit,
482 PRInt32& aRunLimit,
483 PRInt32& aRunLength,
484 PRInt32& aRunCount,
485 PRUint8& aCharType,
486 PRUint8& aPrevCharType) const;
488 void StripBidiControlCharacters(PRUnichar* aText,
489 PRInt32& aTextLength) const;
490 nsAutoString mBuffer;
491 nsVoidArray mLogicalFrames;
492 nsVoidArray mVisualFrames;
493 nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
494 PRInt32 mArraySize;
495 PRInt32* mIndexMap;
496 PRUint8* mLevels;
497 nsresult mSuccess;
499 nsBidi* mBidiEngine;
502 #endif /* nsBidiPresUtils_h___ */
504 #endif // IBMBIDI