@@ -689,7 +689,7 @@ public void mergeDiacritic(TextPosition diacritic)
689
689
break ;
690
690
}
691
691
float currCharXEnd = currCharXStart + widths [i ];
692
-
692
+
693
693
// this is the case where there is an overlap of the diacritic character with the
694
694
// current character and the previous character. If no previous character, just append
695
695
// the diacritic after the current one
@@ -759,16 +759,25 @@ private void insertDiacritic(int i, TextPosition diacritic)
759
759
float [] widths2 = new float [widths .length + 1 ];
760
760
System .arraycopy (widths , 0 , widths2 , 0 , i );
761
761
762
+ // First we add a zero-width entry for the diacritic in the widths array
763
+ widths2 [i ] = widths [i ];
764
+ widths2 [i + 1 ] = 0 ;
765
+ System .arraycopy (widths , i + 1 , widths2 , i + 2 , widths .length - i - 1 );
766
+
762
767
// Unicode combining diacritics always go after the base character, regardless of whether
763
768
// the string is in presentation order or logical order
764
769
sb .append (unicode .charAt (i ));
765
- widths2 [i ] = widths [i ];
770
+
771
+ // If a surrogate starts at the current position, make sure we preserve it
772
+ if (i < unicode .length () - 1 && Character .isSurrogatePair (unicode .charAt (i ), unicode .charAt (i + 1 ))) {
773
+ sb .append (unicode .charAt (i + 1 ));
774
+ i ++;
775
+ }
776
+
766
777
sb .append (combineDiacritic (diacritic .getUnicode ()));
767
- widths2 [i + 1 ] = 0 ;
768
778
769
779
// get the rest of the string
770
780
sb .append (unicode .substring (i + 1 ));
771
- System .arraycopy (widths , i + 1 , widths2 , i + 2 , widths .length - i - 1 );
772
781
773
782
unicode = sb .toString ();
774
783
widths = widths2 ;
0 commit comments