summaryrefslogtreecommitdiffstats
path: root/unix/tkUnixRFont.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tkUnixRFont.c')
-rw-r--r--unix/tkUnixRFont.c85
1 files changed, 62 insertions, 23 deletions
diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c
index ccf77a3..4f7f6f3 100644
--- a/unix/tkUnixRFont.c
+++ b/unix/tkUnixRFont.c
@@ -14,6 +14,14 @@
#include <X11/Xft/Xft.h>
#include <ctype.h>
+/* needed for backport to 8.5 */
+#ifndef ROUND16
+# define ROUND16(x) ((short) floor((x) + 0.5))
+#endif
+#ifndef PI
+# define PI 3.14159265358979323846
+#endif
+
#define MAX_CACHED_COLORS 16
typedef struct {
@@ -614,11 +622,24 @@ TkpGetSubFonts(
*----------------------------------------------------------------------
*/
+/* we need backward compatibility */
+#if TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 7
+# define UNICHAR Tcl_UniChar
+# define TkUtfToUniChar Tcl_UtfToUniChar
+#else /* if !(TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 7) */
+# define UNICHAR int
+# if TCL_UTF_MAX > 4
+# define TkUtfToUniChar Tcl_UtfToUniChar
+# else /* if TCL_UTF_MAX <= 4 */
+extern int TkUtfToUniChar(const char *src, int *chPtr);
+# endif /* TCL_UTF_MAX > 4 */
+#endif /* TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 7 */
+
void
TkpGetFontAttrsForChar(
Tk_Window tkwin, /* Window on the font's display */
Tk_Font tkfont, /* Font to query */
- int c, /* Character of interest */
+ UNICHAR c, /* Character of interest */
TkFontAttributes *faPtr) /* Output: Font attributes */
{
UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
@@ -671,7 +692,7 @@ Tk_MeasureChars(
curByte = 0;
sawNonSpace = 0;
while (numBytes > 0) {
- int unichar;
+ UNICHAR unichar;
clen = TkUtfToUniChar(source, &unichar);
c = (FcChar32) unichar;
@@ -859,6 +880,10 @@ Tk_DrawChars(
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ if (maxCoord <= y) {
+ return; /* nothing to draw */
+ }
+
if (fontPtr->ftDraw == 0) {
#if DEBUG_FONTSEL
printf("Switch to drawable 0x%x\n", drawable);
@@ -879,7 +904,7 @@ Tk_DrawChars(
XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
}
nspec = 0;
- while (numBytes > 0 && x <= maxCoord && y <= maxCoord) {
+ while (numBytes > 0) {
XftFont *ftFont;
FcChar32 c;
@@ -896,19 +921,25 @@ Tk_DrawChars(
ftFont = GetFont(fontPtr, c, 0.0);
if (ftFont) {
- specs[nspec].font = ftFont;
+ int cx = x;
+ int cy = y;
+
specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
- specs[nspec].x = x;
- specs[nspec].y = y;
XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1,
&metrics);
- x += metrics.xOff;
- y += metrics.yOff;
- nspec++;
- if (nspec == NUM_SPEC) {
- XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
- specs, nspec);
- nspec = 0;
+ if ((x += metrics.xOff) >= maxCoord
+ || (y += metrics.yOff) >= maxCoord) {
+ break;
+ }
+ if (metrics.xOff > 0 && cx >= 0 && cy >= 0) {
+ specs[nspec].font = ftFont;
+ specs[nspec].x = cx;
+ specs[nspec].y = cy;
+ if (++nspec == NUM_SPEC) {
+ XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
+ specs, nspec);
+ nspec = 0;
+ }
}
}
}
@@ -1011,8 +1042,7 @@ TkDrawAngledChars(
currentFtFont = NULL;
originX = originY = 0; /* lint */
- while (numBytes > 0 && x <= maxCoord && x >= minCoord && y <= maxCoord
- && y >= minCoord) {
+ while (numBytes > 0 && x >= minCoord && y >= minCoord) {
XftFont *ftFont;
FcChar32 c;
@@ -1050,8 +1080,17 @@ TkDrawAngledChars(
XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
nglyph, &metrics);
nglyph = 0;
- x += metrics.xOff;
- y += metrics.yOff;
+ /*
+ * Breaking at this place is sub-optimal, but the whole algorithm
+ * has a design problem, the choice of NUM_SPEC is arbitrary, and so
+ * the inter-glyph spacing will look arbitrary. This algorithm
+ * has to draw the whole string at once (or whole blocks with same
+ * font), this requires a dynamic 'glyphs' array. In case of overflow
+ * the array has to be divided until the maximal string will fit. (GC)
+ */
+ if ((x += metrics.xOff) >= maxCoord || (y += metrics.yOff) >= maxCoord) {
+ break;
+ }
}
currentFtFont = ftFont;
}
@@ -1087,8 +1126,7 @@ TkDrawAngledChars(
XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
}
nspec = 0;
- while (numBytes > 0 && x <= maxCoord && x >= minCoord
- && y <= maxCoord && y >= minCoord) {
+ while (numBytes > 0 && x >= minCoord && y >= minCoord) {
XftFont *ftFont, *ft0Font;
FcChar32 c;
@@ -1112,10 +1150,11 @@ TkDrawAngledChars(
specs[nspec].y = ROUND16(y);
XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,
&metrics);
- x += metrics.xOff*cosA + metrics.yOff*sinA;
- y += metrics.yOff*cosA - metrics.xOff*sinA;
- nspec++;
- if (nspec == NUM_SPEC) {
+ if ((x += metrics.xOff*cosA + metrics.yOff*sinA) > maxCoord
+ || (y += metrics.yOff*cosA - metrics.xOff*sinA) > maxCoord) {
+ break;
+ }
+ if (++nspec == NUM_SPEC) {
XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
specs, nspec);
nspec = 0;