summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2010-01-05 08:49:47 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2010-01-05 08:49:47 (GMT)
commitaacf8d739e27f7131d0a7322da993ba8158df5e6 (patch)
treeb53ca9c943b91ed43676acd0f73612577ebae655
parenta580567464cda1d5a6116339acc707e451e7854e (diff)
downloadtk-aacf8d739e27f7131d0a7322da993ba8158df5e6.zip
tk-aacf8d739e27f7131d0a7322da993ba8158df5e6.tar.gz
tk-aacf8d739e27f7131d0a7322da993ba8158df5e6.tar.bz2
Corrected rounding of coordinates when working with fonts. [Bug 2824916]
-rw-r--r--ChangeLog18
-rw-r--r--generic/tkFont.c4
-rw-r--r--generic/tkFont.h8
-rw-r--r--unix/tkUnixFont.c42
-rw-r--r--unix/tkUnixRFont.c31
-rw-r--r--win/tkWinFont.c6
6 files changed, 81 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 57e3984..c4c9ec2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,21 @@
+2010-01-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tkFont.h (ROUND16): [Bug 2824916]: Use a correct rounding
+ * unix/tkUnixFont.c (TkpDrawAngledChars): macro for converting a
+ * unix/tkUnixRFont.c (TkpDrawAngledChars): double to a short. This
+ * win/tkWinFont.c (GetScreenFont): stops a number of small
+ visual artefacts from happening and reduces the effect of others. The
+ ROUND16 macro is now shared across all the font code (though some
+ platforms do not need it specially).
+
2010-01-04 Pat Thoyts <patthoyts@users.sourceforge.net>
- * doc/TkInitStubs.3: [Bug 2192104] Mention USE_TK_STUBS macro.
- * library/dialog.tcl: [Bug 2811266] <Return> binding should invoke
+ * doc/TkInitStubs.3: [Bug 2192104]: Mention USE_TK_STUBS macro.
+ * library/dialog.tcl: [Bug 2811266]: <Return> binding should invoke
the button with the focus.
- * library/fontchooser.tcl: [Bug 2727476] Fix default size of font
+ * library/fontchooser.tcl: [Bug 2727476]: Fix default size of font
chooser dialog and assigned minimum sizes for the lists.
- * library/console.tcl: [Bug 580361] Fix console <<Cut>> binding.
+ * library/console.tcl: [Bug 580361]: Fix console <<Cut>> binding.
* library/console.tcl: Fix keyboard access to console menu.
* library/demos/filebox.tcl: Make prettier using ttk.
* library/demos/fontchoose.tcl: Fix display of demo code.
diff --git a/generic/tkFont.c b/generic/tkFont.c
index 56018af..54b3afa 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -10,14 +10,12 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkFont.c,v 1.64 2010/01/03 21:21:33 patthoyts Exp $
+ * RCS: @(#) $Id: tkFont.c,v 1.65 2010/01/05 08:49:49 dkf Exp $
*/
#include "tkInt.h"
#include "tkFont.h"
-#define ROUND16(x) ((short)((x) + 0.5))
-
/*
* The following structure is used to keep track of all the fonts that exist
* in the current application. It must be stored in the TkMainInfo for the
diff --git a/generic/tkFont.h b/generic/tkFont.h
index 5a16d01..ebf5bca 100644
--- a/generic/tkFont.h
+++ b/generic/tkFont.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: tkFont.h,v 1.13 2008/11/05 23:29:58 nijtmans Exp $
+ * RCS: @(#) $Id: tkFont.h,v 1.14 2010/01/05 08:49:49 dkf Exp $
*/
#ifndef _TKFONT
@@ -189,6 +189,12 @@ typedef struct TkXLFDAttributes {
#define XLFD_NUMFIELDS 13 /* Number of fields in XLFD. */
/*
+ * Helper macro. How to correctly round a double to a short.
+ */
+
+#define ROUND16(x) ((short) round(x))
+
+/*
* Low-level API exported by generic code to platform-specific code.
*/
diff --git a/unix/tkUnixFont.c b/unix/tkUnixFont.c
index ba78339..3b9beae 100644
--- a/unix/tkUnixFont.c
+++ b/unix/tkUnixFont.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixFont.c,v 1.40 2009/01/28 20:47:49 nijtmans Exp $
+ * RCS: @(#) $Id: tkUnixFont.c,v 1.41 2010/01/05 08:49:49 dkf Exp $
*/
#include "tkUnixInt.h"
@@ -3010,7 +3010,7 @@ GetEncodingAlias(
EncodingAlias *aliasPtr;
for (aliasPtr = encodingAliases; aliasPtr->aliasPattern != NULL; ) {
- if (Tcl_StringMatch((char *) name, aliasPtr->aliasPattern)) {
+ if (Tcl_StringMatch(name, aliasPtr->aliasPattern)) {
return aliasPtr->realName;
}
aliasPtr++;
@@ -3018,6 +3018,28 @@ GetEncodingAlias(
return name;
}
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpDrawAngledChars --
+ *
+ * Draw some characters at an angle. This is awkward here because we have
+ * no reliable way of drawing any characters at an angle in classic X11;
+ * we have to draw on a Pixmap which is converted to an XImage (from
+ * helper function GetImageOfText), rotate the image (hokey code!) onto
+ * another XImage (from helper function InitDestImage), and then use the
+ * rotated image as a mask when drawing. This is pretty awful; improved
+ * versions are welcomed!
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Target drawable is updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
static inline XImage *
GetImageOfText(
Display *display, /* Display on which to draw. */
@@ -3179,32 +3201,32 @@ TkpDrawAngledChars(
for (j=0 ; j<srcHeight ; j++) {
switch (quadrant) {
case Q0:
- dx = floor(i*cosA + j*sinA + 0.5);
- dy = floor(j*cosA + (srcWidth - i)*sinA + 0.5);
+ dx = ROUND16(i*cosA + j*sinA);
+ dy = ROUND16(j*cosA + (srcWidth - i)*sinA);
break;
case R1:
dx = j;
dy = srcWidth - i;
break;
case Q1:
- dx = floor((i - srcWidth)*cosA + j*sinA + 0.5);
- dy = floor((srcWidth-i)*sinA + (j-srcHeight)*cosA + 0.5);
+ dx = ROUND16((i - srcWidth)*cosA + j*sinA);
+ dy = ROUND16((srcWidth-i)*sinA + (j-srcHeight)*cosA);
break;
case R2:
dx = srcWidth - i;
dy = srcHeight - j;
break;
case Q2:
- dx = floor((i-srcWidth)*cosA + (j-srcHeight)*sinA + 0.5);
- dy = floor((j - srcHeight)*cosA - i*sinA + 0.5);
+ dx = ROUND16((i-srcWidth)*cosA + (j-srcHeight)*sinA);
+ dy = ROUND16((j - srcHeight)*cosA - i*sinA);
break;
case R3:
dx = srcHeight - j;
dy = i;
break;
default:
- dx = floor(i*cosA + (j - srcHeight)*sinA + 0.5);
- dy = floor(j*cosA - i*sinA + 0.5);
+ dx = ROUND16(i*cosA + (j - srcHeight)*sinA);
+ dy = ROUND16(j*cosA - i*sinA);
}
if (dx < 0 || dy < 0 || dx >= bufWidth || dy >= bufHeight) {
diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c
index eef42d5..34f504e 100644
--- a/unix/tkUnixRFont.c
+++ b/unix/tkUnixRFont.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixRFont.c,v 1.32 2010/01/02 18:40:35 dkf Exp $
+ * RCS: @(#) $Id: tkUnixRFont.c,v 1.33 2010/01/05 08:49:50 dkf Exp $
*/
#include "tkUnixInt.h"
@@ -16,8 +16,6 @@
#include <X11/Xft/Xft.h>
#include <ctype.h>
-#define ROUND16(x) ((short)((x) + 0.5))
-
typedef struct {
XftFont *ftFont;
XftFont *ft0Font;
@@ -827,6 +825,25 @@ Tk_DrawChars(
}
}
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpDrawAngledChars --
+ *
+ * Draw some characters at an angle. This would be simple code, except
+ * Xft has bugs with cumulative errors in character positioning which are
+ * caused by trying to perform all calculations internally with integers.
+ * So we have to do the work ourselves with floating-point math.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Target drawable is updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
void
TkpDrawAngledChars(
Display *display, /* Display on which to draw. */
@@ -923,8 +940,8 @@ TkpDrawAngledChars(
XftDrawGlyphs(fontPtr->ftDraw, &fontPtr->color, currentFtFont,
originX, originY, glyphs, nglyph);
}
- originX = (int) floor(x + 0.5);
- originY = (int) floor(y + 0.5);
+ originX = ROUND16(x);
+ originY = ROUND16(y);
if (nglyph) {
XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
nglyph, &metrics);
@@ -993,8 +1010,8 @@ TkpDrawAngledChars(
if (ftFont && ft0Font) {
specs[nspec].font = ftFont;
specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
- specs[nspec].x = (int) floor(x + 0.5);
- specs[nspec].y = (int) floor(y + 0.5);
+ specs[nspec].x = ROUND16(x);
+ specs[nspec].y = ROUND16(y);
XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,
&metrics);
x += metrics.xOff*cosA + metrics.yOff*sinA;
diff --git a/win/tkWinFont.c b/win/tkWinFont.c
index 79df98c..715228b 100644
--- a/win/tkWinFont.c
+++ b/win/tkWinFont.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinFont.c,v 1.47 2009/10/29 09:44:55 patthoyts Exp $
+ * RCS: @(#) $Id: tkWinFont.c,v 1.48 2010/01/05 08:49:50 dkf Exp $
*/
#include "tkWinInt.h"
@@ -2500,8 +2500,8 @@ GetScreenFont(
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -pixelSize;
lf.lfWidth = 0;
- lf.lfEscapement = (int) floor(angle * 10 + 0.5);
- lf.lfOrientation = (int) floor(angle * 10 + 0.5);
+ lf.lfEscapement = ROUND16(angle * 10);
+ lf.lfOrientation = ROUND16(angle * 10);
lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
lf.lfItalic = faPtr->slant;
lf.lfUnderline = faPtr->underline;