@@ -176,14 +176,28 @@ virtual public bool GetParagraph(int runDirection) {
176176 if ( totalTextLength == 0 )
177177 return true ;
178178
179- if ( runDirection == PdfWriter . RUN_DIRECTION_LTR || runDirection == PdfWriter . RUN_DIRECTION_RTL ) {
179+ if ( runDirection != PdfWriter . RUN_DIRECTION_NO_BIDI ) {
180180 if ( orderLevels . Length < totalTextLength ) {
181181 orderLevels = new byte [ pieceSize ] ;
182182 indexChars = new int [ pieceSize ] ;
183183 }
184184
185185 ArabicLigaturizer . ProcessNumbers ( text , 0 , totalTextLength , arabicOptions ) ;
186- BidiOrder order = new BidiOrder ( text , 0 , totalTextLength , ( sbyte ) ( runDirection == PdfWriter . RUN_DIRECTION_RTL ? 1 : 0 ) ) ;
186+ sbyte paragraphEmbeddingLevel ;
187+ switch ( runDirection )
188+ {
189+ case PdfWriter . RUN_DIRECTION_LTR :
190+ paragraphEmbeddingLevel = 0 ;
191+ break ;
192+ case PdfWriter . RUN_DIRECTION_RTL :
193+ paragraphEmbeddingLevel = 1 ;
194+ break ;
195+ case PdfWriter . RUN_DIRECTION_DEFAULT :
196+ default :
197+ paragraphEmbeddingLevel = - 1 ;
198+ break ;
199+ }
200+ BidiOrder order = new BidiOrder ( text , 0 , totalTextLength , paragraphEmbeddingLevel ) ;
187201 byte [ ] od = order . GetLevels ( ) ;
188202 for ( int k = 0 ; k < totalTextLength ; ++ k ) {
189203 orderLevels [ k ] = od [ k ] ;
@@ -243,7 +257,7 @@ virtual public void Save() {
243257 Array . Copy ( text , 0 , storedText , 0 , totalTextLength ) ;
244258 Array . Copy ( detailChunks , 0 , storedDetailChunks , 0 , totalTextLength ) ;
245259 }
246- if ( runDirection == PdfWriter . RUN_DIRECTION_LTR || runDirection == PdfWriter . RUN_DIRECTION_RTL ) {
260+ if ( runDirection != PdfWriter . RUN_DIRECTION_NO_BIDI ) {
247261 if ( storedOrderLevels . Length < totalTextLength ) {
248262 storedOrderLevels = new byte [ totalTextLength ] ;
249263 storedIndexChars = new int [ totalTextLength ] ;
@@ -264,7 +278,7 @@ virtual public void Restore() {
264278 Array . Copy ( storedText , 0 , text , 0 , totalTextLength ) ;
265279 Array . Copy ( storedDetailChunks , 0 , detailChunks , 0 , totalTextLength ) ;
266280 }
267- if ( runDirection == PdfWriter . RUN_DIRECTION_LTR || runDirection == PdfWriter . RUN_DIRECTION_RTL ) {
281+ if ( runDirection != PdfWriter . RUN_DIRECTION_NO_BIDI ) {
268282 Array . Copy ( storedOrderLevels , currentChar , orderLevels , currentChar , totalTextLength - currentChar ) ;
269283 Array . Copy ( storedIndexChars , currentChar , indexChars , currentChar , totalTextLength - currentChar ) ;
270284 }
@@ -348,6 +362,7 @@ virtual public PdfLine ProcessLine(float leftX, float width, int alignment, int
348362 float charWidth = 0 ;
349363 PdfChunk lastValidChunk = null ;
350364 TabStop tabStop = null ;
365+ IList < TabStop > rtlTabsToBeAligned = new List < TabStop > ( ) ;
351366 float tabStopAnchorPosition = float . NaN ;
352367 float tabPosition = float . NaN ;
353368 bool surrogate = false ;
@@ -394,14 +409,7 @@ virtual public PdfLine ProcessLine(float leftX, float width, int alignment, int
394409 if ( ck . IsAttribute ( Chunk . TABSETTINGS ) ) {
395410 lastSplit = currentChar ;
396411 if ( tabStop != null ) {
397- float tabStopPosition = tabStop . GetPosition ( tabPosition , originalWidth - width ,
398- tabStopAnchorPosition ) ;
399- width = originalWidth - ( tabStopPosition + ( originalWidth - width - tabPosition ) ) ;
400- if ( width < 0 ) {
401- tabStopPosition += width ;
402- width = 0 ;
403- }
404- tabStop . Position = tabStopPosition ;
412+ width = ProcessTabStop ( tabStop , tabPosition , originalWidth , width , tabStopAnchorPosition , isRTL , rtlTabsToBeAligned ) ;
405413 }
406414
407415 tabStop = PdfChunk . GetTabStop ( ck , originalWidth - width ) ;
@@ -468,16 +476,12 @@ virtual public PdfLine ProcessLine(float leftX, float width, int alignment, int
468476 }
469477
470478 if ( tabStop != null ) {
471- float tabStopPosition = tabStop . GetPosition ( tabPosition , originalWidth - width , tabStopAnchorPosition ) ;
472- width -= tabStopPosition - tabPosition ;
473- if ( width < 0 ) {
474- tabStopPosition += width ;
475- width = 0 ;
479+ width = ProcessTabStop ( tabStop , tabPosition , originalWidth , width , tabStopAnchorPosition , isRTL , rtlTabsToBeAligned ) ;
480+ }
481+ if ( rtlTabsToBeAligned != null ) {
482+ foreach ( TabStop rtlTabStop in rtlTabsToBeAligned ) {
483+ rtlTabStop . Position = originalWidth - width - rtlTabStop . Position ;
476484 }
477- if ( ! isRTL )
478- tabStop . Position = tabStopPosition ;
479- else
480- tabStop . Position = originalWidth - width - tabPosition ;
481485 }
482486
483487 if ( currentChar >= totalTextLength ) {
@@ -521,6 +525,27 @@ virtual public PdfLine ProcessLine(float leftX, float width, int alignment, int
521525 return new PdfLine ( 0 , originalWidth , originalWidth - GetWidth ( oldCurrentChar , newCurrentChar , originalWidth ) , alignment , false , CreateArrayOfPdfChunks ( oldCurrentChar , newCurrentChar ) , isRTL ) ;
522526 }
523527
528+ private float ProcessTabStop ( TabStop tabStop , float tabPosition , float originalWidth , float width , float tabStopAnchorPosition , bool isRTL , IList < TabStop > rtlTabsToBeAligned )
529+ {
530+ float tabStopPosition = tabStop . GetPosition ( tabPosition , originalWidth - width , tabStopAnchorPosition ) ;
531+ width -= tabStopPosition - tabPosition ;
532+ if ( width < 0 )
533+ {
534+ tabStopPosition += width ;
535+ width = 0 ;
536+ }
537+ if ( ! isRTL )
538+ {
539+ tabStop . Position = tabStopPosition ;
540+ }
541+ else
542+ {
543+ tabStop . Position = tabPosition ; // This will be mirrored when we know exact line width
544+ rtlTabsToBeAligned . Add ( tabStop ) ;
545+ }
546+ return width ;
547+ }
548+
524549 /**
525550 * Call this after processLine() to know if any word was split into several lines.
526551 * @return
@@ -608,7 +633,7 @@ virtual public List<PdfChunk> CreateArrayOfPdfChunks(int startIdx, int endIdx) {
608633 }
609634
610635 virtual public List < PdfChunk > CreateArrayOfPdfChunks ( int startIdx , int endIdx , PdfChunk extraPdfChunk ) {
611- bool bidi = ( runDirection == PdfWriter . RUN_DIRECTION_LTR || runDirection == PdfWriter . RUN_DIRECTION_RTL ) ;
636+ bool bidi = ( runDirection != PdfWriter . RUN_DIRECTION_NO_BIDI ) ;
612637 if ( bidi )
613638 Reorder ( startIdx , endIdx ) ;
614639 List < PdfChunk > ar = new List < PdfChunk > ( ) ;
@@ -656,14 +681,14 @@ virtual public int[] GetWord(int startIdx, int idx) {
656681 int first = idx ;
657682 // forward
658683 for ( ; last < totalTextLength ; ++ last ) {
659- if ( ! char . IsLetter ( text [ last ] ) && ! char . IsDigit ( text [ last ] ) )
684+ if ( ! char . IsLetter ( text [ last ] ) && ! char . IsDigit ( text [ last ] ) && text [ last ] != ' \u00AD ' )
660685 break ;
661686 }
662687 if ( last == idx )
663688 return null ;
664689 // backward
665690 for ( ; first >= startIdx ; -- first ) {
666- if ( ! char . IsLetter ( text [ first ] ) && ! char . IsDigit ( text [ first ] ) )
691+ if ( ! char . IsLetter ( text [ first ] ) && ! char . IsDigit ( text [ first ] ) && text [ first ] != ' \u00AD ' )
667692 break ;
668693 }
669694 ++ first ;
0 commit comments