From e12ef8efd22290667ca8025a561c41bd0a0dc872 Mon Sep 17 00:00:00 2001 From: vincentdarley Date: Fri, 21 Nov 2003 18:51:18 +0000 Subject: correct handling of interpolated tabs using fractional pixel widths --- ChangeLog | 9 +++++++++ generic/tkText.c | 22 +++++++++++++++++++++- generic/tkText.h | 8 +++++++- generic/tkTextDisp.c | 35 ++++++++++++----------------------- tests/textDisp.test | 34 +++++++++++++++------------------- 5 files changed, 64 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index b7bfcd1..238519e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2003-11-21 Vince Darley + * generic/tkTextDisp.c: + * generic/tkText.h: + * generic/tkText.c: + * tests/textDisp.test: ensure interpolated tabs are at the same + location as the equivalent real tabs, by making use of fractional + rather than integer pixel calculations. + +2003-11-21 Vince Darley + * generic/tkTextDisp.c: prevent wrapped line height calculations until the widget has actually been given a geometry. diff --git a/generic/tkText.c b/generic/tkText.c index 133d88d..c5c8baa 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkText.c,v 1.44 2003/11/15 02:33:50 vincentdarley Exp $ + * RCS: @(#) $Id: tkText.c,v 1.45 2003/11/21 18:51:18 vincentdarley Exp $ */ #include "default.h" @@ -3310,6 +3310,7 @@ TkTextGetTabs(interp, tkwin, stringPtr) TkTextTabArray *tabArrayPtr; TkTextTab *tabPtr; Tcl_UniChar ch; + double prevStop, lastStop; /* Map these strings to TkTextTabAlign values */ @@ -3342,6 +3343,8 @@ TkTextGetTabs(interp, tkwin, stringPtr) tabArrayPtr = (TkTextTabArray *) ckalloc((unsigned) (sizeof(TkTextTabArray) + (count-1)*sizeof(TkTextTab))); tabArrayPtr->numTabs = 0; + prevStop = 0.0; + lastStop = 0.0; for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < objc; i++, tabPtr++) { int index; @@ -3349,6 +3352,14 @@ TkTextGetTabs(interp, tkwin, stringPtr) != TCL_OK) { goto error; } + + prevStop = lastStop; + if (Tk_GetMMFromObj(interp, tkwin, objv[i], &lastStop) != TCL_OK) { + goto error; + } + lastStop *= WidthOfScreen(Tk_Screen(tkwin)); + lastStop /= WidthMMOfScreen(Tk_Screen(tkwin)); + tabArrayPtr->numTabs++; /* @@ -3373,6 +3384,15 @@ TkTextGetTabs(interp, tkwin, stringPtr) } tabPtr->alignment = ((TkTextTabAlign)index); } + + /* + * For when we need to interpolate tab stops, store + * these two so we know the tab stop size to very + * high precision. + */ + tabArrayPtr->lastTab = lastStop; + tabArrayPtr->tabIncrement = lastStop - prevStop; + return tabArrayPtr; error: diff --git a/generic/tkText.h b/generic/tkText.h index ee19ad2..bf79bc7 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkText.h,v 1.21 2003/11/15 02:33:50 vincentdarley Exp $ + * RCS: @(#) $Id: tkText.h,v 1.22 2003/11/21 18:51:18 vincentdarley Exp $ */ #ifndef _TKTEXT @@ -474,6 +474,12 @@ typedef struct TkTextTab { typedef struct TkTextTabArray { int numTabs; /* Number of tab stops. */ + double lastTab; /* The accurate fractional pixel + * position of the last tab. */ + double tabIncrement; /* The accurate fractional pixel + * increment between interpolated + * tabs we have to create when + * we exceed numTabs. */ TkTextTab tabs[1]; /* Array of tabs. The actual size * will be numTabs. THIS FIELD MUST * BE THE LAST IN THE STRUCTURE. */ diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 623570a..b218a79 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkTextDisp.c,v 1.34 2003/11/21 17:29:13 vincentdarley Exp $ + * RCS: @(#) $Id: tkTextDisp.c,v 1.35 2003/11/21 18:51:18 vincentdarley Exp $ */ #include "tkPort.h" @@ -6596,7 +6596,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) int x, desired, delta, width, decimal, i, gotDigit; TkTextDispChunk *chunkPtr2, *decimalChunkPtr; CharInfo *ciPtr; - int tabX, prev, spaceWidth; + int tabX, spaceWidth; char *p; TkTextTabAlign alignment; @@ -6633,15 +6633,10 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) * from the last two tab positions. */ - if (tabArrayPtr->numTabs > 1) { - prev = tabArrayPtr->tabs[tabArrayPtr->numTabs-2].location; - } else { - prev = 0; - } + tabX = (int) (tabArrayPtr->lastTab + + (index + 1 - tabArrayPtr->numTabs) + * tabArrayPtr->tabIncrement + 0.5); alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment; - tabX = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - + (index + 1 - tabArrayPtr->numTabs) - * (tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - prev); } if (alignment == LEFT) { @@ -6780,7 +6775,7 @@ SizeOfTab(textPtr, tabArrayPtr, indexPtr, x, maxX) int maxX; /* X-location of pixel just past the * right edge of the line. */ { - int tabX, prev, result, index, spaceWidth; + int tabX, result, index, spaceWidth; TkTextTabAlign alignment; index = *indexPtr; @@ -6796,7 +6791,7 @@ SizeOfTab(textPtr, tabArrayPtr, indexPtr, x, maxX) do { /* - * We were given the count before this tabs, so increment it + * We were given the count before this tab, so increment it * first. */ index++; @@ -6805,18 +6800,12 @@ SizeOfTab(textPtr, tabArrayPtr, indexPtr, x, maxX) alignment = tabArrayPtr->tabs[index].alignment; } else { /* - * Ran out of tab stops; compute a tab position by extrapolating - * from the last two tab positions. + * Ran out of tab stops; compute a tab position by + * extrapolating. */ - - if (tabArrayPtr->numTabs > 1) { - prev = tabArrayPtr->tabs[tabArrayPtr->numTabs-2].location; - } else { - prev = 0; - } - tabX = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - + (index + 1 - tabArrayPtr->numTabs) - * (tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - prev); + tabX = (int) (tabArrayPtr->lastTab + + (index + 1 - tabArrayPtr->numTabs) + * tabArrayPtr->tabIncrement + 0.5); alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment; } /* diff --git a/tests/textDisp.test b/tests/textDisp.test index 48a4567..31abdd1 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -6,7 +6,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: textDisp.test,v 1.21 2003/11/21 17:29:13 vincentdarley Exp $ +# RCS: @(#) $Id: textDisp.test,v 1.22 2003/11/21 18:51:18 vincentdarley Exp $ package require tcltest 2.1 eval tcltest::configure $argv @@ -3166,27 +3166,23 @@ test textDisp-27.7 {SizeOfTab procedure, center alignment, wrap -none (potential lset res 0 [expr {[lindex $res 0] - $tab}] set res } [list 0 [expr {$fixedDiff + 18}] 7 $fixedHeight] -test textDisp-27.7.1 {SizeOfTab procedure, fractional tab interpolation problem} {knownBug textfonts} { +test textDisp-27.7.1 {SizeOfTab procedure, fractional tab interpolation problem} { .t delete 1.0 end - set cm [winfo fpixels .t 1c] - .t configure -tabs {1c 2c 3c 4c} -wrap none -width 40 - .t insert 1.0 a\tb\tc\td\te\n012345678934567890a\tbb\tcc\tdd - set width [expr {$fixedWidth * 19}] - set tab $cm - while {$tab < $width} { - set tab [expr {$tab + $cm}] + set interpolatetab {1c 2c} + set precisetab {} + for {set i 1} {$i < 20} {incr i} { + lappend precisetab "${i}c" } - # Now we've calculated to the end of the tab after 'a', add one - # more for 'bb\t' and we're there, with 4 for the border - set tab [expr {4 + int($tab + $cm)}] + .t configure -tabs $interpolatetab -wrap none -width 150 + .t insert 1.0 [string repeat "a\t" 20] update - set res [.t bbox 2.23] - # Now, on some platforms Tk interpolated from 3c-4c->5c but that - # interpolation doesn't use fractional pixels and so this result - # might be off by one. - lset res 0 [expr {[lindex $res 0] - $tab}] - set res -} [list 0 [expr {$fixedDiff + 18}] 7 $fixedHeight] + set res [.t bbox 1.20] + # Now, Tk's interpolated tabs should be the same as + # non-interpolated. + .t configure -tabs $precisetab + update + expr {[lindex $res 0] - [lindex [.t bbox 1.20] 0]} +} {0} .t configure -wrap char -tabs {} -width 20 update -- cgit v0.12