Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / layout / base / nsBidiPresUtils.h
blob0976cfce5b66a09deddf623da267b1bbe2dee484
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 "nsTArray.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 #ifdef DrawText
55 #undef DrawText
56 #endif
58 /**
59 * A structure representing some continuation state for each frame on the line,
60 * used to determine the first and the last continuation frame for each
61 * continuation chain on the line.
63 struct nsFrameContinuationState : public nsVoidPtrHashKey
65 nsFrameContinuationState(const void *aFrame) : nsVoidPtrHashKey(aFrame) {}
67 /**
68 * The first visual frame in the continuation chain containing this frame, or
69 * nsnull if this frame is the first visual frame in the chain.
71 nsIFrame* mFirstVisualFrame;
73 /**
74 * The number of frames in the continuation chain containing this frame, if
75 * this frame is the first visual frame of the chain, or 0 otherwise.
77 PRUint32 mFrameCount;
79 /**
80 * TRUE if this frame is the first visual frame of its continuation chain on
81 * this line and the chain has some frames on the previous lines.
83 PRPackedBool mHasContOnPrevLines;
85 /**
86 * TRUE if this frame is the first visual frame of its continuation chain on
87 * this line and the chain has some frames left for next lines.
89 PRPackedBool mHasContOnNextLines;
93 * Following type is used to pass needed hashtable to reordering methods
95 typedef nsTHashtable<nsFrameContinuationState> nsContinuationStates;
97 /**
98 * A structure representing a logical position which should be resolved
99 * into its visual position during BiDi processing.
101 struct nsBidiPositionResolve
103 // [in] Logical index within string.
104 PRInt32 logicalIndex;
105 // [out] Visual index within string.
106 // If the logical position was not found, set to kNotFound.
107 PRInt32 visualIndex;
108 // [out] Visual position of the character, from the left (on the X axis), in twips.
109 // 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.
110 // If the logical position was not found, set to kNotFound.
111 PRInt32 visualLeftTwips;
112 // [out] Visual width of the character, in twips.
113 // If the logical position was not found, set to kNotFound.
114 PRInt32 visualWidth;
117 class nsBidiPresUtils {
118 public:
119 nsBidiPresUtils();
120 ~nsBidiPresUtils();
121 PRBool IsSuccessful(void) const;
124 * Interface for the processor used by ProcessText. Used by process text to
125 * collect information about the width of subruns and to notify where each
126 * subrun should be rendered.
128 class BidiProcessor {
129 public:
130 virtual ~BidiProcessor() { }
133 * Sets the current text with the given length and the given direction.
135 * @remark The reason that the function gives a string instead of an index
136 * is that ProcessText copies and modifies the string passed to it, so
137 * passing an index would be impossible.
139 * @param aText The string of text.
140 * @param aLength The length of the string of text.
141 * @param aDirection The direction of the text. The string will never have
142 * mixed direction.
144 virtual void SetText(const PRUnichar* aText,
145 PRInt32 aLength,
146 nsBidiDirection aDirection) = 0;
149 * Returns the measured width of the text given in SetText. If SetText was
150 * not called with valid parameters, the result of this call is undefined.
151 * This call is guaranteed to only be called once between SetText calls.
152 * Will be invoked before DrawText.
154 virtual nscoord GetWidth() = 0;
157 * Draws the text given in SetText to a rendering context. If SetText was
158 * not called with valid parameters, the result of this call is undefined.
159 * This call is guaranteed to only be called once between SetText calls.
161 * @param aXOffset The offset of the left side of the substring to be drawn
162 * from the beginning of the overall string passed to ProcessText.
163 * @param aWidth The width returned by GetWidth.
165 virtual void DrawText(nscoord aXOffset,
166 nscoord aWidth) = 0;
170 * Make Bidi engine calculate the embedding levels of the frames that are
171 * descendants of a given block frame.
173 * @param aBlockFrame The block frame
175 * @lina 06/18/2000
177 nsresult Resolve(nsBlockFrame* aBlockFrame);
180 * Reorder this line using Bidi engine.
181 * Update frame array, following the new visual sequence.
183 * @lina 05/02/2000
185 void ReorderFrames(nsIFrame* aFirstFrameOnLine,
186 PRInt32 aNumFramesOnLine);
189 * Format Unicode text, taking into account bidi capabilities
190 * of the platform. The formatting includes: reordering, Arabic shaping,
191 * symmetric and numeric swapping, removing control characters.
193 * @lina 06/18/2000
195 nsresult FormatUnicodeText(nsPresContext* aPresContext,
196 PRUnichar* aText,
197 PRInt32& aTextLength,
198 nsCharType aCharType,
199 PRBool aIsOddLevel);
202 * Reorder plain text using the Unicode Bidi algorithm and send it to
203 * a rendering context for rendering.
205 * @param[in] aText the string to be rendered (in logical order)
206 * @param aLength the number of characters in the string
207 * @param aBaseDirection the base direction of the string
208 * NSBIDI_LTR - left-to-right string
209 * NSBIDI_RTL - right-to-left string
210 * @param aPresContext the presentation context
211 * @param aRenderingContext the rendering context to render to
212 * @param aTextRunConstructionContext the rendering context to be used to construct the textrun (affects font hinting)
213 * @param aX the x-coordinate to render the string
214 * @param aY the y-coordinate to render the string
215 * @param[in,out] aPosResolve array of logical positions to resolve into visual positions; can be nsnull if this functionality is not required
216 * @param aPosResolveCount number of items in the aPosResolve array
218 nsresult RenderText(const PRUnichar* aText,
219 PRInt32 aLength,
220 nsBidiDirection aBaseDirection,
221 nsPresContext* aPresContext,
222 nsIRenderingContext& aRenderingContext,
223 nsIRenderingContext& aTextRunConstructionContext,
224 nscoord aX,
225 nscoord aY,
226 nsBidiPositionResolve* aPosResolve = nsnull,
227 PRInt32 aPosResolveCount = 0)
229 return ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext, aRenderingContext,
230 aTextRunConstructionContext, 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,
241 aRenderingContext, aRenderingContext,
242 MODE_MEASURE, 0, 0, nsnull, 0, &length);
243 return NS_SUCCEEDED(rv) ? length : 0;
247 * Check if a line is reordered, i.e., if the child frames are not
248 * all laid out left-to-right.
249 * @param aFirstFrameOnLine : first frame of the line to be tested
250 * @param aNumFramesOnLine : number of frames on this line
251 * @param[out] aLeftMost : leftmost frame on this line
252 * @param[out] aRightMost : rightmost frame on this line
254 PRBool CheckLineOrder(nsIFrame* aFirstFrameOnLine,
255 PRInt32 aNumFramesOnLine,
256 nsIFrame** aLeftmost,
257 nsIFrame** aRightmost);
260 * Get the frame to the right of the given frame, on the same line.
261 * @param aFrame : We're looking for the frame to the right of this frame.
262 * If null, return the leftmost frame on the line.
263 * @param aFirstFrameOnLine : first frame of the line to be tested
264 * @param aNumFramesOnLine : number of frames on this line
266 nsIFrame* GetFrameToRightOf(const nsIFrame* aFrame,
267 nsIFrame* aFirstFrameOnLine,
268 PRInt32 aNumFramesOnLine);
271 * Get the frame to the left of the given frame, on the same line.
272 * @param aFrame : We're looking for the frame to the left of this frame.
273 * If null, return the rightmost frame on the line.
274 * @param aFirstFrameOnLine : first frame of the line to be tested
275 * @param aNumFramesOnLine : number of frames on this line
277 nsIFrame* GetFrameToLeftOf(const nsIFrame* aFrame,
278 nsIFrame* aFirstFrameOnLine,
279 PRInt32 aNumFramesOnLine);
282 * Get the bidi embedding level of the given (inline) frame.
284 static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame);
287 * Get the bidi base level of the given (inline) frame.
289 static nsBidiLevel GetFrameBaseLevel(nsIFrame* aFrame);
291 enum Mode { MODE_DRAW, MODE_MEASURE };
294 * Reorder plain text using the Unicode Bidi algorithm and send it to
295 * a processor for rendering or measuring
297 * @param[in] aText the string to be processed (in logical order)
298 * @param aLength the number of characters in the string
299 * @param aBaseDirection the base direction of the string
300 * NSBIDI_LTR - left-to-right string
301 * NSBIDI_RTL - right-to-left string
302 * @param aPresContext the presentation context
303 * @param aprocessor the bidi processor
304 * @param aMode the operation to process
305 * MODE_DRAW - invokes DrawText on the processor for each substring
306 * MODE_MEASURE - does not invoke DrawText on the processor
307 * Note that the string is always measured, regardless of mode
308 * @param[in,out] aPosResolve array of logical positions to resolve into
309 * visual positions; can be nsnull if this functionality is not required
310 * @param aPosResolveCount number of items in the aPosResolve array
311 * @param[out] aWidth Pointer to where the width will be stored (may be null)
313 nsresult ProcessText(const PRUnichar* aText,
314 PRInt32 aLength,
315 nsBidiDirection aBaseDirection,
316 nsPresContext* aPresContext,
317 BidiProcessor& aprocessor,
318 Mode aMode,
319 nsBidiPositionResolve* aPosResolve,
320 PRInt32 aPosResolveCount,
321 nscoord* aWidth);
324 * Make a copy of a string, converting from logical to visual order
326 * @param aSource the source string
327 * @param aDest the destination string
328 * @param aBaseDirection the base direction of the string
329 * (NSBIDI_LTR or NSBIDI_RTL to force the base direction;
330 * NSBIDI_DEFAULT_LTR or NSBIDI_DEFAULT_RTL to let the bidi engine
331 * determine the direction from rules P2 and P3 of the bidi algorithm.
332 * @see nsBidi::GetPara
333 * @param aOverride if TRUE, the text has a bidi override, according to
334 * the direction in aDir
336 void CopyLogicalToVisual(const nsAString& aSource,
337 nsAString& aDest,
338 nsBidiLevel aBaseDirection,
339 PRBool aOverride);
342 * Guess at how much memory is being used by this nsBidiPresUtils instance,
343 * including memory used by nsBidi.
345 PRUint32 EstimateMemoryUsed();
347 void Traverse(nsCycleCollectionTraversalCallback &cb) const;
348 void Unlink();
350 private:
351 nsresult ProcessTextForRenderingContext(const PRUnichar* aText,
352 PRInt32 aLength,
353 nsBidiDirection aBaseDirection,
354 nsPresContext* aPresContext,
355 nsIRenderingContext& aRenderingContext,
356 nsIRenderingContext& aTextRunConstructionContext,
357 Mode aMode,
358 nscoord aX, // DRAW only
359 nscoord aY, // DRAW only
360 nsBidiPositionResolve* aPosResolve, /* may be null */
361 PRInt32 aPosResolveCount,
362 nscoord* aWidth /* may be null */);
365 * Create a string containing entire text content of this block.
367 * @lina 05/02/2000
369 void CreateBlockBuffer();
372 * Set up an array of the frames after splitting frames so that each frame has
373 * consistent directionality. At this point the frames are still in logical
374 * order
376 void InitLogicalArray(nsIFrame* aCurrentFrame);
379 * Initialize the logically-ordered array of frames
380 * using the top-level frames of a single line
382 void InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine,
383 PRInt32 aNumFramesOnLine);
386 * Reorder the frame array from logical to visual order
388 * @param aReordered TRUE on return if the visual order is different from
389 * the logical order
390 * @param aHasRTLFrames TRUE on return if at least one of the frames is RTL
391 * (and therefore might have reordered descendents)
393 nsresult Reorder(PRBool& aReordered, PRBool& aHasRTLFrames);
396 * Position aFrame and it's descendants to their visual places. Also if aFrame
397 * is not leaf, resize it to embrace it's children.
399 * @param aFrame The frame which itself and its children are going
400 * to be repositioned
401 * @param aIsOddLevel TRUE means the embedding level of this frame is odd
402 * @param[in,out] aLeft IN value is the starting position of aFrame(without
403 * considering its left margin)
404 * OUT value will be the ending position of aFrame(after
405 * adding its right margin)
406 * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
408 void RepositionFrame(nsIFrame* aFrame,
409 PRBool aIsOddLevel,
410 nscoord& aLeft,
411 nsContinuationStates* aContinuationStates) const;
414 * Initialize the continuation state(nsFrameContinuationState) to
415 * (nsnull, 0) for aFrame and its descendants.
417 * @param aFrame The frame which itself and its descendants will
418 * be initialized
419 * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
421 void InitContinuationStates(nsIFrame* aFrame,
422 nsContinuationStates* aContinuationStates) const;
425 * Determine if aFrame is leftmost or rightmost, and set aIsLeftMost and
426 * aIsRightMost values. Also set continuation states of aContinuationStates.
428 * A frame is leftmost if it's the first appearance of its continuation chain
429 * on the line and the chain is on its first line if it's LTR or the chain is
430 * on its last line if it's RTL.
431 * A frame is rightmost if it's the last appearance of its continuation chain
432 * on the line and the chain is on its first line if it's RTL or the chain is
433 * on its last line if it's LTR.
435 * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
436 * @param[out] aIsLeftMost TRUE means aFrame is leftmost frame or continuation
437 * @param[out] aIsRightMost TRUE means aFrame is rightmost frame or continuation
439 void IsLeftOrRightMost(nsIFrame* aFrame,
440 nsContinuationStates* aContinuationStates,
441 PRBool& aIsLeftMost /* out */,
442 PRBool& aIsRightMost /* out */) const;
445 * Adjust frame positions following their visual order
447 * @param aFirstChild the first kid
449 * @lina 04/11/2000
451 void RepositionInlineFrames(nsIFrame* aFirstChild) const;
454 * Helper method for Resolve()
455 * Truncate a text frame to the end of a single-directional run and possibly
456 * create a continuation frame for the remainder of its content.
458 * @param aFrame the original frame
459 * @param aNewFrame [OUT] the new frame that was created
460 * @param aFrameIndex [IN/OUT] index of aFrame in mLogicalFrames
461 * @param aStart [IN] the start of the content mapped by aFrame (and
462 * any fluid continuations)
463 * @param aEnd [IN] the offset of the end of the single-directional
464 * text run.
465 * @see Resolve()
466 * @see RemoveBidiContinuation()
468 inline
469 void EnsureBidiContinuation(nsIFrame* aFrame,
470 nsIFrame** aNewFrame,
471 PRInt32& aFrameIndex,
472 PRInt32 aStart,
473 PRInt32 aEnd);
476 * Helper method for Resolve()
477 * Convert one or more bidi continuation frames created in a previous reflow by
478 * EnsureBidiContinuation() into fluid continuations.
479 * @param aFrame the frame whose continuations are to be removed
480 * @param aFirstIndex index of aFrame in mLogicalFrames
481 * @param aLastIndex index of the last frame to be removed
482 * @param aOffset [OUT] count of directional frames removed. Since
483 * directional frames have control characters
484 * corresponding to them in mBuffer, the pointers to
485 * mBuffer in Resolve() will need to be updated after
486 * deleting the frames.
488 * @see Resolve()
489 * @see EnsureBidiContinuation()
491 void RemoveBidiContinuation(nsIFrame* aFrame,
492 PRInt32 aFirstIndex,
493 PRInt32 aLastIndex,
494 PRInt32& aOffset) const;
495 void CalculateCharType(PRInt32& aOffset,
496 PRInt32 aCharTypeLimit,
497 PRInt32& aRunLimit,
498 PRInt32& aRunLength,
499 PRInt32& aRunCount,
500 PRUint8& aCharType,
501 PRUint8& aPrevCharType) const;
503 void StripBidiControlCharacters(PRUnichar* aText,
504 PRInt32& aTextLength) const;
506 static PRBool WriteLogicalToVisual(const PRUnichar* aSrc,
507 PRUint32 aSrcLength,
508 PRUnichar* aDest,
509 nsBidiLevel aBaseDirection,
510 nsBidi* aBidiEngine);
512 static void WriteReverse(const PRUnichar* aSrc,
513 PRUint32 aSrcLength,
514 PRUnichar* aDest);
516 nsAutoString mBuffer;
517 nsTArray<nsIFrame*> mLogicalFrames;
518 nsTArray<nsIFrame*> mVisualFrames;
519 nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
520 PRInt32 mArraySize;
521 PRInt32* mIndexMap;
522 PRUint8* mLevels;
523 nsresult mSuccess;
525 nsBidi* mBidiEngine;
528 #endif /* nsBidiPresUtils_h___ */
530 #endif // IBMBIDI