diff options
| author | Matthias Melcher <git@matthiasm.com> | 2019-02-01 18:18:28 +0100 |
|---|---|---|
| committer | Matthias Melcher <git@matthiasm.com> | 2019-02-01 18:18:28 +0100 |
| commit | 389521a8852b9e40329349c13b7d6a9016b04c44 (patch) | |
| tree | e7644715e1eb925800e5caa6ea0d31f3db580001 /src | |
| parent | ab90f849ff1fc577468d9a24ae6dbd0080d358de (diff) | |
Additional fix for STR #2531
Wiggeling characters in Fl_Text_Display due to advanced kerning.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Text_Display.cxx | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index 205404a93..4d940a917 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -1967,10 +1967,23 @@ int Fl_Text_Display::handle_vline( // FIXME: we need to allow two modes for FIND_INDEX: one on the edge of the // FIXME: character for selection, and one on the character center for cursors. - int i, X, startIndex, style, charStyle; - int startStyle, styleX; + + /* STR #2531 + + The variables startStyle and styleX seem to introduce some additional + complexity. They were required to fix STR #2531 in which a horizontal + character wiggle could be observed when drag-selecting text. This was caused + by native drawing an measuring routines that support kerning (inter-character + spacing, the width of 'T' plus the width of 'e' is greater than the width of + 'Te', because advanced typesetting moves the 'e' slightly to the left below + the 'T'). + + To acommodate this, FLTK uses slightly different routines for a true style + change vs. a change in highlighting only. + */ + int i, X, startIndex, startStyle, style, charStyle; char *lineStr; - double startX; + double startX, styleX; if ( lineStartPos == -1 ) { lineStr = NULL; @@ -1994,8 +2007,8 @@ int Fl_Text_Display::handle_vline( X = text_area.x - mHorizOffset; } - startX = styleX = X; - startIndex = startStyle = 0; + startX = X; + startIndex = 0; if (!lineStr) { // just clear the background if (mode==DRAW_LINE) { @@ -2008,8 +2021,8 @@ int Fl_Text_Display::handle_vline( } return 0; } - char currChar = 0, prevChar = 0; + styleX = startX; startStyle = startIndex; // draw the line style = position_style(lineStartPos, lineLen, 0); for (i=0; i<lineLen; ) { @@ -2022,10 +2035,10 @@ int Fl_Text_Display::handle_vline( double w = 0; if (prevChar=='\t') { // draw a single Tab space - styleX = startX; startStyle = startIndex; double tab = col_to_x(mBuffer->tab_distance()); double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; w = ((int(xAbs/tab)+1)*tab) - xAbs; + styleX = startX+w; startStyle = i; if (mode==DRAW_LINE) draw_string( style|BG_ONLY_MASK, startX, Y, startX+w, 0, 0 ); if (mode==FIND_INDEX && startX+w>rightClip) { @@ -2036,19 +2049,15 @@ int Fl_Text_Display::handle_vline( return lineStartPos + startIndex; } } else { - // draw a text segment + // draw the text segment from the previous style change up to this point if ( (style&0xff)==(charStyle&0xff)) { - w = string_width( lineStr+startStyle, i-startStyle, style ) + styleX - startX; + w = string_width( lineStr+startStyle, i-startStyle, style ) - startX + styleX; } else { - styleX = startX; startStyle = startIndex; w = string_width( lineStr+startIndex, i-startIndex, style ); } if (mode==DRAW_LINE) { - // STR 2531: if only the highlighting changes, but the style is the same, - // we must use some tricky clipping, or kerning between characters will - // make the text wiggle while the user is expanding a selection. - if ( (style&0xff)==(charStyle&0xff)) { - fl_push_clip(startX, Y, w, mMaxsize); + if (startIndex!=startStyle) { + fl_push_clip(startX, Y, w+1, mMaxsize); draw_string( style, styleX, Y, startX+w, lineStr+startStyle, i-startStyle ); fl_pop_clip(); } else { @@ -2057,10 +2066,21 @@ int Fl_Text_Display::handle_vline( } if (mode==FIND_INDEX && startX+w>rightClip) { // find x pos inside block - int di = find_x(lineStr+startIndex, i-startIndex, style, -(rightClip-startX)); // STR #2788 + int di; + if (startIndex!=startStyle) { + di = find_x(lineStr+startStyle, i-startStyle, style, -(rightClip-styleX)); // STR #2788 + di = lineStartPos + startStyle + di; + } else { + di = find_x(lineStr+startIndex, i-startIndex, style, -(rightClip-startX)); // STR #2788 + di = lineStartPos + startIndex + di; + } free(lineStr); IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) - return lineStartPos + startIndex + di; + return di; + } + if ( (style&0xff)!=(charStyle&0xff)) { + startStyle = i; + styleX = startX+w; } } style = charStyle; @@ -2089,8 +2109,8 @@ int Fl_Text_Display::handle_vline( w = string_width( lineStr+startIndex, i-startIndex, style ); if (mode==DRAW_LINE) { // STR 2531 - if ( (style&0xff)==(charStyle&0xff)) { - fl_push_clip(startX, Y, w, mMaxsize); + if (startIndex!=startStyle) { + fl_push_clip(startX, Y, w+1, mMaxsize); draw_string( style, styleX, Y, startX+w, lineStr+startStyle, i-startStyle ); fl_pop_clip(); } else { @@ -2099,10 +2119,17 @@ int Fl_Text_Display::handle_vline( } if (mode==FIND_INDEX) { // find x pos inside block - int di = find_x(lineStr+startIndex, i-startIndex, style, -(rightClip-startX)); // STR #2788 + int di; + if (startIndex!=startStyle) { + di = find_x(lineStr+startStyle, i-startStyle, style, -(rightClip-styleX)); // STR #2788 + di = lineStartPos + startStyle + di; + } else { + di = find_x(lineStr+startIndex, i-startIndex, style, -(rightClip-startX)); // STR #2788 + di = lineStartPos + startIndex + di; + } free(lineStr); IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) - return lineStartPos + startIndex + di; + return di; } } if (mode==GET_WIDTH) { |
