• R/O
  • SSH
  • HTTPS

azuki: コミット


コミットメタ情報

リビジョン1061 (tree)
日時2020-09-13 14:50:56
作者sgry

ログメッセージ

fix: 折り返し表示時、特定条件で例外が発生

折り返し表示時で、描画トークンが描画領域右端にオーバーラップするとき、
その中で画面上に表示されない後半の文字を切り捨てる処理がある。
この処理において、切り捨て位置を描画トークンの内容ではなく Document
の内容から判断していた。その結果、切断位置が描画トークンの長さよりも
後ろになることがあり、そのような場合に ArgumentOutOfRangeException
を発生することとなっていた。

本件はフォーラム #42910 で報告いただいた不具合の修正となる (Special
Thanks: @kkato233)。また、trunk (master) でのみ顕在化する不具合であり
1.7 以前のバージョンでは発生しない。

https://github.com/sgryjp/azuki/commit/fa4b3e461b4f521e6955bd45fe7fd0bf55054db3

変更サマリ

差分

--- trunk/Azuki/TextUtil.cs (revision 1060)
+++ trunk/Azuki/TextUtil.cs (revision 1061)
@@ -491,6 +491,21 @@
491491 return index;
492492 }
493493
494+ public static int NextGraphemeClusterIndex(string text, int index)
495+ {
496+ Debug.Assert(text != null);
497+ Debug.Assert(0 <= index);
498+ Debug.Assert(index < text.Length);
499+
500+ do
501+ {
502+ index++;
503+ }
504+ while (index < text.Length && IsUndividableIndex(text, index));
505+
506+ return index;
507+ }
508+
494509 public static int PrevGraphemeClusterIndex( IList<char> text, int index )
495510 {
496511 Debug.Assert( text != null );
--- trunk/Azuki/View/PropWrapView.cs (revision 1060)
+++ trunk/Azuki/View/PropWrapView.cs (revision 1061)
@@ -731,19 +731,23 @@
731731 // (if the clip-rect's right boundary is NOT the text area's right boundary,
732732 // we must write one more char so that the peeking char appears at the boundary.)
733733
734- // try to get graphically peeking (drawn over the border line) char
735- var peekingChar = new TextSegment( visCharCount, TextUtil.NextGraphemeClusterIndex(Document.InternalBuffer, visCharCount) );
734+ // find the graphically peeking character at the right end of the view
735+ // and discard characters following it
736+ if( visCharCount < token.Length )
737+ {
738+ var peekingChar = new TextSegment( visCharCount, TextUtil.NextGraphemeClusterIndex(token, visCharCount) );
736739
737- // calculate right end coordinate of the peeking char
738- if( peekingChar.IsEmpty == false )
739- {
740- peekingCharRight = MeasureTokenEndX( g, peekingChar, visPartRight );
740+ // calculate right end coordinate of the peeking char
741+ if( peekingChar.IsEmpty == false )
742+ {
743+ peekingCharRight = MeasureTokenEndX( g, peekingChar, visPartRight );
744+ }
745+
746+ // cut trailing extra
747+ token = token.Substring( 0, visCharCount+peekingChar.Length );
748+ tokenEndPos.X = (peekingCharRight != 0) ? peekingCharRight : visPartRight;
741749 }
742750
743- // cut trailing extra
744- token = token.Substring( 0, visCharCount+peekingChar.Length );
745- tokenEndPos.X = (peekingCharRight != 0) ? peekingCharRight : visPartRight;
746-
747751 // to terminate this loop, set token end position to invalid one
748752 end = Int32.MaxValue;
749753 }
旧リポジトリブラウザで表示