summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Melcher <git@matthiasm.com>2019-02-01 18:18:28 +0100
committerMatthias Melcher <git@matthiasm.com>2019-02-01 18:18:28 +0100
commit389521a8852b9e40329349c13b7d6a9016b04c44 (patch)
treee7644715e1eb925800e5caa6ea0d31f3db580001 /src
parentab90f849ff1fc577468d9a24ae6dbd0080d358de (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.cxx69
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) {