2007-03-22 10:30:00 -07:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* * * * * * BEGIN LICENSE BLOCK * * * * *
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is mozilla . org code .
*
* The Initial Developer of the Original Code is
* IBM Corporation .
* Portions created by the Initial Developer are Copyright ( C ) 2000
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
* IBM Corporation
*
* Alternatively , the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later ( the " GPL " ) ,
* or the GNU Lesser General Public License Version 2.1 or later ( the " LGPL " ) ,
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above . If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL , and not to allow others to
* use your version of this file under the terms of the MPL , indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL . If you do not delete
* the provisions above , a recipient may use your version of this file under
* the terms of any one of the MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
# ifdef IBMBIDI
# ifndef nsBidiPresUtils_h___
# define nsBidiPresUtils_h___
2009-02-03 06:42:18 -08:00
# include "nsTArray.h"
2007-03-22 10:30:00 -07:00
# include "nsIFrame.h"
# include "nsBidi.h"
# include "nsBidiUtils.h"
# include "nsCOMPtr.h"
# include "nsDataHashtable.h"
# include "nsBlockFrame.h"
# include "nsTHashtable.h"
2010-06-12 04:37:59 -07:00
# ifdef DrawText
# undef DrawText
# endif
2007-03-22 10:30:00 -07:00
/**
* A structure representing some continuation state for each frame on the line ,
* used to determine the first and the last continuation frame for each
* continuation chain on the line .
*/
struct nsFrameContinuationState : public nsVoidPtrHashKey
{
nsFrameContinuationState ( const void * aFrame ) : nsVoidPtrHashKey ( aFrame ) { }
/**
* The first visual frame in the continuation chain containing this frame , or
* nsnull if this frame is the first visual frame in the chain .
*/
nsIFrame * mFirstVisualFrame ;
/**
* The number of frames in the continuation chain containing this frame , if
* this frame is the first visual frame of the chain , or 0 otherwise .
*/
PRUint32 mFrameCount ;
/**
* TRUE if this frame is the first visual frame of its continuation chain on
* this line and the chain has some frames on the previous lines .
*/
PRPackedBool mHasContOnPrevLines ;
/**
* TRUE if this frame is the first visual frame of its continuation chain on
* this line and the chain has some frames left for next lines .
*/
PRPackedBool mHasContOnNextLines ;
} ;
/*
* Following type is used to pass needed hashtable to reordering methods
*/
typedef nsTHashtable < nsFrameContinuationState > nsContinuationStates ;
/**
* A structure representing a logical position which should be resolved
* into its visual position during BiDi processing .
*/
struct nsBidiPositionResolve
{
// [in] Logical index within string.
PRInt32 logicalIndex ;
// [out] Visual index within string.
// If the logical position was not found, set to kNotFound.
PRInt32 visualIndex ;
// [out] Visual position of the character, from the left (on the X axis), in twips.
// 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.
// If the logical position was not found, set to kNotFound.
PRInt32 visualLeftTwips ;
2009-03-21 01:38:14 -07:00
// [out] Visual width of the character, in twips.
// If the logical position was not found, set to kNotFound.
PRInt32 visualWidth ;
2007-03-22 10:30:00 -07:00
} ;
class nsBidiPresUtils {
public :
nsBidiPresUtils ( ) ;
~ nsBidiPresUtils ( ) ;
PRBool IsSuccessful ( void ) const ;
2008-07-18 11:29:06 -07:00
/**
* Interface for the processor used by ProcessText . Used by process text to
* collect information about the width of subruns and to notify where each
* subrun should be rendered .
*/
class BidiProcessor {
public :
virtual ~ BidiProcessor ( ) { }
/**
* Sets the current text with the given length and the given direction .
*
* @ remark The reason that the function gives a string instead of an index
* is that ProcessText copies and modifies the string passed to it , so
* passing an index would be impossible .
*
* @ param aText The string of text .
* @ param aLength The length of the string of text .
* @ param aDirection The direction of the text . The string will never have
* mixed direction .
*/
virtual void SetText ( const PRUnichar * aText ,
PRInt32 aLength ,
nsBidiDirection aDirection ) = 0 ;
/**
* Returns the measured width of the text given in SetText . If SetText was
* not called with valid parameters , the result of this call is undefined .
* This call is guaranteed to only be called once between SetText calls .
* Will be invoked before DrawText .
*/
virtual nscoord GetWidth ( ) = 0 ;
/**
* Draws the text given in SetText to a rendering context . If SetText was
* not called with valid parameters , the result of this call is undefined .
* This call is guaranteed to only be called once between SetText calls .
*
* @ param aXOffset The offset of the left side of the substring to be drawn
* from the beginning of the overall string passed to ProcessText .
* @ param aWidth The width returned by GetWidth .
*/
virtual void DrawText ( nscoord aXOffset ,
nscoord aWidth ) = 0 ;
} ;
2007-03-22 10:30:00 -07:00
/**
* Make Bidi engine calculate the embedding levels of the frames that are
* descendants of a given block frame .
*
* @ param aBlockFrame The block frame
*
* @ lina 06 / 18 / 2000
*/
2010-04-25 05:15:17 -07:00
nsresult Resolve ( nsBlockFrame * aBlockFrame ) ;
2007-03-22 10:30:00 -07:00
/**
* Reorder this line using Bidi engine .
* Update frame array , following the new visual sequence .
*
* @ lina 05 / 02 / 2000
*/
2007-08-29 02:19:16 -07:00
void ReorderFrames ( nsIFrame * aFirstFrameOnLine ,
2007-03-22 10:30:00 -07:00
PRInt32 aNumFramesOnLine ) ;
/**
* Format Unicode text , taking into account bidi capabilities
* of the platform . The formatting includes : reordering , Arabic shaping ,
* symmetric and numeric swapping , removing control characters .
*
* @ lina 06 / 18 / 2000
*/
nsresult FormatUnicodeText ( nsPresContext * aPresContext ,
PRUnichar * aText ,
PRInt32 & aTextLength ,
nsCharType aCharType ,
2008-08-11 08:19:01 -07:00
PRBool aIsOddLevel ) ;
2007-03-22 10:30:00 -07:00
/**
* Reorder plain text using the Unicode Bidi algorithm and send it to
* a rendering context for rendering .
*
* @ param [ in ] aText the string to be rendered ( in logical order )
* @ param aLength the number of characters in the string
* @ param aBaseDirection the base direction of the string
* NSBIDI_LTR - left - to - right string
* NSBIDI_RTL - right - to - left string
* @ param aPresContext the presentation context
2011-01-16 12:23:33 -08:00
* @ param aRenderingContext the rendering context to render to
* @ param aTextRunConstructionContext the rendering context to be used to construct the textrun ( affects font hinting )
2007-03-22 10:30:00 -07:00
* @ param aX the x - coordinate to render the string
* @ param aY the y - coordinate to render the string
* @ param [ in , out ] aPosResolve array of logical positions to resolve into visual positions ; can be nsnull if this functionality is not required
* @ param aPosResolveCount number of items in the aPosResolve array
*/
nsresult RenderText ( const PRUnichar * aText ,
PRInt32 aLength ,
nsBidiDirection aBaseDirection ,
nsPresContext * aPresContext ,
nsIRenderingContext & aRenderingContext ,
2011-01-16 12:23:33 -08:00
nsIRenderingContext & aTextRunConstructionContext ,
2007-03-22 10:30:00 -07:00
nscoord aX ,
nscoord aY ,
nsBidiPositionResolve * aPosResolve = nsnull ,
PRInt32 aPosResolveCount = 0 )
{
2008-07-18 11:29:06 -07:00
return ProcessTextForRenderingContext ( aText , aLength , aBaseDirection , aPresContext , aRenderingContext ,
2011-01-16 12:23:33 -08:00
aTextRunConstructionContext , MODE_DRAW , aX , aY , aPosResolve , aPosResolveCount , nsnull ) ;
2007-03-22 10:30:00 -07:00
}
nscoord MeasureTextWidth ( const PRUnichar * aText ,
PRInt32 aLength ,
nsBidiDirection aBaseDirection ,
nsPresContext * aPresContext ,
nsIRenderingContext & aRenderingContext )
{
nscoord length ;
2011-01-16 12:23:33 -08:00
nsresult rv = ProcessTextForRenderingContext ( aText , aLength , aBaseDirection , aPresContext ,
aRenderingContext , aRenderingContext ,
2008-07-18 11:29:06 -07:00
MODE_MEASURE , 0 , 0 , nsnull , 0 , & length ) ;
2007-03-22 10:30:00 -07:00
return NS_SUCCEEDED ( rv ) ? length : 0 ;
}
/**
* Check if a line is reordered , i . e . , if the child frames are not
* all laid out left - to - right .
* @ param aFirstFrameOnLine : first frame of the line to be tested
* @ param aNumFramesOnLine : number of frames on this line
* @ param [ out ] aLeftMost : leftmost frame on this line
* @ param [ out ] aRightMost : rightmost frame on this line
*/
PRBool CheckLineOrder ( nsIFrame * aFirstFrameOnLine ,
PRInt32 aNumFramesOnLine ,
nsIFrame * * aLeftmost ,
nsIFrame * * aRightmost ) ;
/**
* Get the frame to the right of the given frame , on the same line .
* @ param aFrame : We ' re looking for the frame to the right of this frame .
* If null , return the leftmost frame on the line .
* @ param aFirstFrameOnLine : first frame of the line to be tested
* @ param aNumFramesOnLine : number of frames on this line
*/
nsIFrame * GetFrameToRightOf ( const nsIFrame * aFrame ,
nsIFrame * aFirstFrameOnLine ,
PRInt32 aNumFramesOnLine ) ;
/**
* Get the frame to the left of the given frame , on the same line .
* @ param aFrame : We ' re looking for the frame to the left of this frame .
* If null , return the rightmost frame on the line .
* @ param aFirstFrameOnLine : first frame of the line to be tested
* @ param aNumFramesOnLine : number of frames on this line
*/
nsIFrame * GetFrameToLeftOf ( const nsIFrame * aFrame ,
nsIFrame * aFirstFrameOnLine ,
PRInt32 aNumFramesOnLine ) ;
/**
* Get the bidi embedding level of the given ( inline ) frame .
*/
static nsBidiLevel GetFrameEmbeddingLevel ( nsIFrame * aFrame ) ;
/**
* Get the bidi base level of the given ( inline ) frame .
*/
static nsBidiLevel GetFrameBaseLevel ( nsIFrame * aFrame ) ;
enum Mode { MODE_DRAW , MODE_MEASURE } ;
2008-07-18 11:29:06 -07:00
/**
* Reorder plain text using the Unicode Bidi algorithm and send it to
* a processor for rendering or measuring
*
* @ param [ in ] aText the string to be processed ( in logical order )
* @ param aLength the number of characters in the string
* @ param aBaseDirection the base direction of the string
* NSBIDI_LTR - left - to - right string
* NSBIDI_RTL - right - to - left string
* @ param aPresContext the presentation context
* @ param aprocessor the bidi processor
* @ param aMode the operation to process
* MODE_DRAW - invokes DrawText on the processor for each substring
* MODE_MEASURE - does not invoke DrawText on the processor
* Note that the string is always measured , regardless of mode
* @ param [ in , out ] aPosResolve array of logical positions to resolve into
* visual positions ; can be nsnull if this functionality is not required
* @ param aPosResolveCount number of items in the aPosResolve array
* @ param [ out ] aWidth Pointer to where the width will be stored ( may be null )
*/
2007-03-22 10:30:00 -07:00
nsresult ProcessText ( const PRUnichar * aText ,
PRInt32 aLength ,
nsBidiDirection aBaseDirection ,
nsPresContext * aPresContext ,
2008-07-18 11:29:06 -07:00
BidiProcessor & aprocessor ,
2007-03-22 10:30:00 -07:00
Mode aMode ,
2008-07-18 11:29:06 -07:00
nsBidiPositionResolve * aPosResolve ,
2007-03-22 10:30:00 -07:00
PRInt32 aPosResolveCount ,
2008-07-18 11:29:06 -07:00
nscoord * aWidth ) ;
2011-01-04 00:52:17 -08:00
/**
* Make a copy of a string , converting from logical to visual order
*
* @ param aSource the source string
* @ param aDest the destination string
* @ param aBaseDirection the base direction of the string
* ( NSBIDI_LTR or NSBIDI_RTL to force the base direction ;
* NSBIDI_DEFAULT_LTR or NSBIDI_DEFAULT_RTL to let the bidi engine
* determine the direction from rules P2 and P3 of the bidi algorithm .
* @ see nsBidi : : GetPara
* @ param aOverride if TRUE , the text has a bidi override , according to
* the direction in aDir
*/
void CopyLogicalToVisual ( const nsAString & aSource ,
nsAString & aDest ,
nsBidiLevel aBaseDirection ,
PRBool aOverride ) ;
2010-05-31 19:19:35 -07:00
/**
* Guess at how much memory is being used by this nsBidiPresUtils instance ,
* including memory used by nsBidi .
*/
PRUint32 EstimateMemoryUsed ( ) ;
2011-01-11 11:19:00 -08:00
void Traverse ( nsCycleCollectionTraversalCallback & cb ) const ;
void Unlink ( ) ;
2008-07-18 11:29:06 -07:00
private :
nsresult ProcessTextForRenderingContext ( const PRUnichar * aText ,
PRInt32 aLength ,
nsBidiDirection aBaseDirection ,
nsPresContext * aPresContext ,
nsIRenderingContext & aRenderingContext ,
2011-01-16 12:23:33 -08:00
nsIRenderingContext & aTextRunConstructionContext ,
2008-07-18 11:29:06 -07:00
Mode aMode ,
nscoord aX , // DRAW only
nscoord aY , // DRAW only
nsBidiPositionResolve * aPosResolve , /* may be null */
PRInt32 aPosResolveCount ,
nscoord * aWidth /* may be null */ ) ;
2007-03-22 10:30:00 -07:00
/**
* Create a string containing entire text content of this block .
*
* @ lina 05 / 02 / 2000
*/
2007-08-29 02:19:16 -07:00
void CreateBlockBuffer ( ) ;
2007-03-22 10:30:00 -07:00
/**
* Set up an array of the frames after splitting frames so that each frame has
* consistent directionality . At this point the frames are still in logical
* order
*/
2007-08-29 02:19:16 -07:00
void InitLogicalArray ( nsIFrame * aCurrentFrame ) ;
2007-03-22 10:30:00 -07:00
/**
* Initialize the logically - ordered array of frames
* using the top - level frames of a single line
*/
void InitLogicalArrayFromLine ( nsIFrame * aFirstFrameOnLine ,
PRInt32 aNumFramesOnLine ) ;
/**
* Reorder the frame array from logical to visual order
*
* @ param aReordered TRUE on return if the visual order is different from
* the logical order
* @ param aHasRTLFrames TRUE on return if at least one of the frames is RTL
* ( and therefore might have reordered descendents )
*/
nsresult Reorder ( PRBool & aReordered , PRBool & aHasRTLFrames ) ;
/*
* Position aFrame and it ' s descendants to their visual places . Also if aFrame
* is not leaf , resize it to embrace it ' s children .
*
* @ param aFrame The frame which itself and its children are going
* to be repositioned
* @ param aIsOddLevel TRUE means the embedding level of this frame is odd
* @ param [ in , out ] aLeft IN value is the starting position of aFrame ( without
* considering its left margin )
* OUT value will be the ending position of aFrame ( after
* adding its right margin )
* @ param aContinuationStates A map from nsIFrame * to nsFrameContinuationState
*/
void RepositionFrame ( nsIFrame * aFrame ,
PRBool aIsOddLevel ,
nscoord & aLeft ,
nsContinuationStates * aContinuationStates ) const ;
/*
* Initialize the continuation state ( nsFrameContinuationState ) to
* ( nsnull , 0 ) for aFrame and its descendants .
*
* @ param aFrame The frame which itself and its descendants will
* be initialized
* @ param aContinuationStates A map from nsIFrame * to nsFrameContinuationState
*/
void InitContinuationStates ( nsIFrame * aFrame ,
nsContinuationStates * aContinuationStates ) const ;
/*
* Determine if aFrame is leftmost or rightmost , and set aIsLeftMost and
* aIsRightMost values . Also set continuation states of aContinuationStates .
*
* A frame is leftmost if it ' s the first appearance of its continuation chain
* on the line and the chain is on its first line if it ' s LTR or the chain is
* on its last line if it ' s RTL .
* A frame is rightmost if it ' s the last appearance of its continuation chain
* on the line and the chain is on its first line if it ' s RTL or the chain is
* on its last line if it ' s LTR .
*
* @ param aContinuationStates A map from nsIFrame * to nsFrameContinuationState
* @ param [ out ] aIsLeftMost TRUE means aFrame is leftmost frame or continuation
* @ param [ out ] aIsRightMost TRUE means aFrame is rightmost frame or continuation
*/
void IsLeftOrRightMost ( nsIFrame * aFrame ,
nsContinuationStates * aContinuationStates ,
PRBool & aIsLeftMost /* out */ ,
PRBool & aIsRightMost /* out */ ) const ;
/**
* Adjust frame positions following their visual order
*
2007-08-29 02:19:16 -07:00
* @ param aFirstChild the first kid
2007-03-22 10:30:00 -07:00
*
* @ lina 04 / 11 / 2000
*/
2007-08-29 02:19:16 -07:00
void RepositionInlineFrames ( nsIFrame * aFirstChild ) const ;
2007-03-22 10:30:00 -07:00
/**
* Helper method for Resolve ( )
2008-01-29 20:13:06 -08:00
* Truncate a text frame to the end of a single - directional run and possibly
* create a continuation frame for the remainder of its content .
2007-03-22 10:30:00 -07:00
*
* @ param aFrame the original frame
* @ param aNewFrame [ OUT ] the new frame that was created
* @ param aFrameIndex [ IN / OUT ] index of aFrame in mLogicalFrames
2008-01-29 20:13:06 -08:00
* @ param aStart [ IN ] the start of the content mapped by aFrame ( and
* any fluid continuations )
* @ param aEnd [ IN ] the offset of the end of the single - directional
* text run .
2007-03-22 10:30:00 -07:00
* @ see Resolve ( )
* @ see RemoveBidiContinuation ( )
*/
2009-04-19 01:19:27 -07:00
inline
void EnsureBidiContinuation ( nsIFrame * aFrame ,
nsIFrame * * aNewFrame ,
PRInt32 & aFrameIndex ,
PRInt32 aStart ,
PRInt32 aEnd ) ;
2007-03-22 10:30:00 -07:00
/**
* Helper method for Resolve ( )
* Convert one or more bidi continuation frames created in a previous reflow by
* EnsureBidiContinuation ( ) into fluid continuations .
* @ param aFrame the frame whose continuations are to be removed
* @ param aFirstIndex index of aFrame in mLogicalFrames
* @ param aLastIndex index of the last frame to be removed
* @ param aOffset [ OUT ] count of directional frames removed . Since
* directional frames have control characters
* corresponding to them in mBuffer , the pointers to
* mBuffer in Resolve ( ) will need to be updated after
* deleting the frames .
*
* @ see Resolve ( )
* @ see EnsureBidiContinuation ( )
*/
2007-08-29 02:19:16 -07:00
void RemoveBidiContinuation ( nsIFrame * aFrame ,
2007-03-22 10:30:00 -07:00
PRInt32 aFirstIndex ,
PRInt32 aLastIndex ,
PRInt32 & aOffset ) const ;
void CalculateCharType ( PRInt32 & aOffset ,
PRInt32 aCharTypeLimit ,
PRInt32 & aRunLimit ,
PRInt32 & aRunLength ,
PRInt32 & aRunCount ,
PRUint8 & aCharType ,
PRUint8 & aPrevCharType ) const ;
void StripBidiControlCharacters ( PRUnichar * aText ,
PRInt32 & aTextLength ) const ;
2011-01-04 00:52:17 -08:00
static PRBool WriteLogicalToVisual ( const PRUnichar * aSrc ,
PRUint32 aSrcLength ,
PRUnichar * aDest ,
nsBidiLevel aBaseDirection ,
nsBidi * aBidiEngine ) ;
static void WriteReverse ( const PRUnichar * aSrc ,
PRUint32 aSrcLength ,
PRUnichar * aDest ) ;
2007-03-22 10:30:00 -07:00
nsAutoString mBuffer ;
2009-02-03 06:42:18 -08:00
nsTArray < nsIFrame * > mLogicalFrames ;
nsTArray < nsIFrame * > mVisualFrames ;
2007-03-22 10:30:00 -07:00
nsDataHashtable < nsISupportsHashKey , PRInt32 > mContentToFrameIndex ;
PRInt32 mArraySize ;
PRInt32 * mIndexMap ;
PRUint8 * mLevels ;
nsresult mSuccess ;
nsBidi * mBidiEngine ;
} ;
# endif /* nsBidiPresUtils_h___ */
# endif // IBMBIDI