summaryrefslogtreecommitdiffstats
path: root/generic/tkFont.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkFont.c')
-rw-r--r--generic/tkFont.c946
1 files changed, 651 insertions, 295 deletions
diff --git a/generic/tkFont.c b/generic/tkFont.c
index 1a6474f..4485df8 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -163,7 +163,7 @@ static const TkStateMap xlfdSetwidthMap[] = {
* configuring a set of font attributes.
*/
-static const char *fontOpt[] = {
+static const char *const fontOpt[] = {
"-family",
"-size",
"-weight",
@@ -188,27 +188,27 @@ static const char *fontOpt[] = {
* the alias list are also automatically tried.
*/
-static char *timesAliases[] = {
+static const char *const timesAliases[] = {
"Times", /* Unix. */
"Times New Roman", /* Windows. */
"New York", /* Mac. */
NULL
};
-static char *helveticaAliases[] = {
+static const char *const helveticaAliases[] = {
"Helvetica", /* Unix. */
"Arial", /* Windows. */
"Geneva", /* Mac. */
NULL
};
-static char *courierAliases[] = {
+static const char *const courierAliases[] = {
"Courier", /* Unix and Mac. */
"Courier New", /* Windows. */
NULL
};
-static char *minchoAliases[] = {
+static const char *const minchoAliases[] = {
"mincho", /* Unix. */
"\357\274\255\357\274\263 \346\230\216\346\234\235",
/* Windows (MS mincho). */
@@ -217,7 +217,7 @@ static char *minchoAliases[] = {
NULL
};
-static char *gothicAliases[] = {
+static const char *const gothicAliases[] = {
"gothic", /* Unix. */
"\357\274\255\357\274\263 \343\202\264\343\202\267\343\203\203\343\202\257",
/* Windows (MS goshikku). */
@@ -226,7 +226,7 @@ static char *gothicAliases[] = {
NULL
};
-static char *dingbatsAliases[] = {
+static const char *const dingbatsAliases[] = {
"dingbats", "zapfdingbats", "itc zapfdingbats",
/* Unix. */
/* Windows. */
@@ -234,7 +234,7 @@ static char *dingbatsAliases[] = {
NULL
};
-static char **fontAliases[] = {
+static const char *const *const fontAliases[] = {
timesAliases,
helveticaAliases,
courierAliases,
@@ -250,7 +250,7 @@ static char **fontAliases[] = {
* be examined also.
*/
-static char *systemClass[] = {
+static const char *const systemClass[] = {
"fixed", /* Unix. */
/* Windows. */
"chicago", "osaka", "sistemny",
@@ -258,7 +258,7 @@ static char *systemClass[] = {
NULL
};
-static char *serifClass[] = {
+static const char *const serifClass[] = {
"times", "palatino", "mincho",
/* All platforms. */
"song ti", /* Unix. */
@@ -268,7 +268,7 @@ static char *serifClass[] = {
NULL
};
-static char *sansClass[] = {
+static const char *const sansClass[] = {
"helvetica", "gothic", /* All platforms. */
/* Unix. */
"ms sans serif", "traditional arabic",
@@ -277,7 +277,7 @@ static char *sansClass[] = {
NULL
};
-static char *monoClass[] = {
+static const char *const monoClass[] = {
"courier", "gothic", /* All platforms. */
"fangsong ti", /* Unix. */
"simplified arabic fixed", /* Windows. */
@@ -285,11 +285,11 @@ static char *monoClass[] = {
NULL
};
-static char *symbolClass[] = {
+static const char *const symbolClass[] = {
"symbol", "dingbats", "wingdings", NULL
};
-static char **fontFallbacks[] = {
+static const char *const *const fontFallbacks[] = {
systemClass,
serifClass,
sansClass,
@@ -304,7 +304,7 @@ static char **fontFallbacks[] = {
* found, all font families in the system are examined.
*/
-static char *globalFontClass[] = {
+static const char *const globalFontClass[] = {
"symbol", /* All platforms. */
/* Unix. */
"lucida sans unicode", /* Windows. */
@@ -325,6 +325,7 @@ static int ConfigAttributesObj(Tcl_Interp *interp,
TkFontAttributes *faPtr);
static void DupFontObjProc(Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr);
static int FieldSpecified(const char *field);
+static void FreeFontObj(Tcl_Obj *objPtr);
static void FreeFontObjProc(Tcl_Obj *objPtr);
static int GetAttributeInfoObj(Tcl_Interp *interp,
const TkFontAttributes *faPtr, Tcl_Obj *objPtr);
@@ -345,7 +346,7 @@ static void UpdateDependentFonts(TkFontInfo *fiPtr,
* font object points to the TkFont structure for the font, or NULL.
*/
-Tcl_ObjType tkFontObjType = {
+const Tcl_ObjType tkFontObjType = {
"font", /* name */
FreeFontObjProc, /* freeIntRepProc */
DupFontObjProc, /* dupIntRepProc */
@@ -376,9 +377,8 @@ void
TkFontPkgInit(
TkMainInfo *mainPtr) /* The application being created. */
{
- TkFontInfo *fiPtr;
+ TkFontInfo *fiPtr = ckalloc(sizeof(TkFontInfo));
- fiPtr = (TkFontInfo *) ckalloc(sizeof(TkFontInfo));
Tcl_InitHashTable(&fiPtr->fontCache, TCL_STRING_KEYS);
Tcl_InitHashTable(&fiPtr->namedTable, TCL_STRING_KEYS);
fiPtr->mainPtr = mainPtr;
@@ -410,14 +410,11 @@ void
TkFontPkgFree(
TkMainInfo *mainPtr) /* The application being deleted. */
{
- TkFontInfo *fiPtr;
+ TkFontInfo *fiPtr = mainPtr->fontInfoPtr;
Tcl_HashEntry *hPtr, *searchPtr;
Tcl_HashSearch search;
- int fontsLeft;
+ int fontsLeft = 0;
- fiPtr = mainPtr->fontInfoPtr;
-
- fontsLeft = 0;
for (searchPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
searchPtr != NULL;
searchPtr = Tcl_NextHashEntry(&search)) {
@@ -438,14 +435,14 @@ TkFontPkgFree(
hPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);
while (hPtr != NULL) {
- ckfree((char *) Tcl_GetHashValue(hPtr));
+ ckfree(Tcl_GetHashValue(hPtr));
hPtr = Tcl_NextHashEntry(&search);
}
Tcl_DeleteHashTable(&fiPtr->namedTable);
- if (fiPtr->updatePending != 0) {
- Tcl_CancelIdleCall(TheWorldHasChanged, (ClientData) fiPtr);
+ if (fiPtr->updatePending) {
+ Tcl_CancelIdleCall(TheWorldHasChanged, fiPtr);
}
- ckfree((char *) fiPtr);
+ ckfree(fiPtr);
}
/*
@@ -473,9 +470,9 @@ Tk_FontObjCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
int index;
- Tk_Window tkwin;
- TkFontInfo *fiPtr;
- static const char *optionStrings[] = {
+ Tk_Window tkwin = clientData;
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ static const char *const optionStrings[] = {
"actual", "configure", "create", "delete",
"families", "measure", "metrics", "names",
NULL
@@ -485,9 +482,6 @@ Tk_FontObjCmd(
FONT_FAMILIES, FONT_MEASURE, FONT_METRICS, FONT_NAMES
};
- tkwin = (Tk_Window) clientData;
- fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
-
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
return TCL_ERROR;
@@ -528,7 +522,7 @@ Tk_FontObjCmd(
s = Tcl_GetString(objv[n]);
if (s[0] == '-' && s[1] != '-') {
optPtr = objv[n];
- ++n;
+ n++;
} else {
optPtr = NULL;
}
@@ -540,7 +534,7 @@ Tk_FontObjCmd(
if (n < objc) {
if (!strcmp(Tcl_GetString(objv[n]), "--")) {
- ++n;
+ n++;
}
}
@@ -550,7 +544,7 @@ Tk_FontObjCmd(
if (n < objc) {
charPtr = objv[n];
- ++n;
+ n++;
}
/*
@@ -575,6 +569,7 @@ Tk_FontObjCmd(
-1, 40, "...");
Tcl_AppendToObj(resultPtr, "\"", -1);
Tcl_SetObjResult(interp, resultPtr);
+ Tcl_SetErrorCode(interp, "TK", "VALUE", "FONT_SAMPLE", NULL);
return TCL_ERROR;
}
uniChar = Tcl_GetUniChar(charPtr, 0);
@@ -606,24 +601,25 @@ Tk_FontObjCmd(
}
case FONT_CONFIGURE: {
int result;
- char *string;
+ const char *string;
Tcl_Obj *objPtr;
NamedFont *nfPtr;
Tcl_HashEntry *namedHashPtr;
if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "fontname ?options?");
+ Tcl_WrongNumArgs(interp, 2, objv, "fontname ?-option value ...?");
return TCL_ERROR;
}
string = Tcl_GetString(objv[2]);
namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string);
nfPtr = NULL; /* lint. */
if (namedHashPtr != NULL) {
- nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
}
- if ((namedHashPtr == NULL) || (nfPtr->deletePending != 0)) {
- Tcl_AppendResult(interp, "named font \"", string,
- "\" doesn't exist", NULL);
+ if ((namedHashPtr == NULL) || nfPtr->deletePending) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "named font \"%s\" doesn't exist", string));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL);
return TCL_ERROR;
}
if (objc == 3) {
@@ -639,13 +635,12 @@ Tk_FontObjCmd(
return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr);
}
case FONT_CREATE: {
- int skip, i;
- char *name;
+ int skip = 3, i;
+ const char *name;
char buf[16 + TCL_INTEGER_SPACE];
TkFontAttributes fa;
Tcl_HashEntry *namedHashPtr;
- skip = 3;
if (objc < 3) {
name = NULL;
} else {
@@ -677,12 +672,12 @@ Tk_FontObjCmd(
if (TkCreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_AppendResult(interp, name, NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
break;
}
case FONT_DELETE: {
int i, result = TCL_OK;
- char *string;
+ const char *string;
/*
* Delete the named font. If there are still widgets using this font,
@@ -693,16 +688,15 @@ Tk_FontObjCmd(
Tcl_WrongNumArgs(interp, 2, objv, "fontname ?fontname ...?");
return TCL_ERROR;
}
- for (i = 2; i < objc && result == TCL_OK; i++) {
+ for (i = 2; (i < objc) && (result == TCL_OK); i++) {
string = Tcl_GetString(objv[i]);
result = TkDeleteNamedFont(interp, tkwin, string);
}
return result;
}
case FONT_FAMILIES: {
- int skip;
+ int skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
- skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
if (skip < 0) {
return TCL_ERROR;
}
@@ -714,10 +708,9 @@ Tk_FontObjCmd(
break;
}
case FONT_MEASURE: {
- char *string;
+ const char *string;
Tk_Font tkfont;
int length = 0, skip = 0;
- Tcl_Obj *resultPtr;
if (objc > 4) {
skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
@@ -726,7 +719,8 @@ Tk_FontObjCmd(
}
}
if (objc - skip != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "font ?-displayof window? text");
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "font ?-displayof window? text");
return TCL_ERROR;
}
tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
@@ -734,8 +728,8 @@ Tk_FontObjCmd(
return TCL_ERROR;
}
string = Tcl_GetStringFromObj(objv[3 + skip], &length);
- resultPtr = Tcl_GetObjResult(interp);
- Tcl_SetIntObj(resultPtr, Tk_TextWidth(tkfont, string, length));
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ Tk_TextWidth(tkfont, string, length)));
Tk_FreeFont(tkfont);
break;
}
@@ -743,7 +737,7 @@ Tk_FontObjCmd(
Tk_Font tkfont;
int skip, index, i;
const TkFontMetrics *fmPtr;
- static const char *switches[] = {
+ static const char *const switches[] = {
"-ascent", "-descent", "-linespace", "-fixed", NULL
};
@@ -764,12 +758,10 @@ Tk_FontObjCmd(
objv += skip;
fmPtr = GetFontMetrics(tkfont);
if (objc == 3) {
- char buf[64 + TCL_INTEGER_SPACE * 4];
-
- sprintf(buf, "-ascent %d -descent %d -linespace %d -fixed %d",
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "-ascent %d -descent %d -linespace %d -fixed %d",
fmPtr->ascent, fmPtr->descent,
- fmPtr->ascent + fmPtr->descent, fmPtr->fixed);
- Tcl_AppendResult(interp, buf, NULL);
+ fmPtr->ascent + fmPtr->descent, fmPtr->fixed));
} else {
if (Tcl_GetIndexFromObj(interp, objv[3], switches, "metric", 0,
&index) != TCL_OK) {
@@ -783,33 +775,35 @@ Tk_FontObjCmd(
case 2: i = fmPtr->ascent + fmPtr->descent; break;
case 3: i = fmPtr->fixed; break;
}
- Tcl_SetIntObj(Tcl_GetObjResult(interp), i);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
}
Tk_FreeFont(tkfont);
break;
}
case FONT_NAMES: {
- char *string;
- NamedFont *nfPtr;
Tcl_HashSearch search;
Tcl_HashEntry *namedHashPtr;
- Tcl_Obj *strPtr, *resultPtr;
+ Tcl_Obj *resultPtr;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "names");
return TCL_ERROR;
}
- resultPtr = Tcl_GetObjResult(interp);
+ resultPtr = Tcl_NewObj();
namedHashPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);
while (namedHashPtr != NULL) {
- nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
- if (nfPtr->deletePending == 0) {
- string = Tcl_GetHashKey(&fiPtr->namedTable, namedHashPtr);
- strPtr = Tcl_NewStringObj(string, -1);
- Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
+ NamedFont *nfPtr = Tcl_GetHashValue(namedHashPtr);
+
+ if (!nfPtr->deletePending) {
+ char *string = Tcl_GetHashKey(&fiPtr->namedTable,
+ namedHashPtr);
+
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(string, -1));
}
namedHashPtr = Tcl_NextHashEntry(&search);
}
+ Tcl_SetObjResult(interp, resultPtr);
break;
}
}
@@ -844,9 +838,8 @@ UpdateDependentFonts(
Tcl_HashEntry *cacheHashPtr;
Tcl_HashSearch search;
TkFont *fontPtr;
- NamedFont *nfPtr;
+ NamedFont *nfPtr = Tcl_GetHashValue(namedHashPtr);
- nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
if (nfPtr->refCount == 0) {
/*
* Well nobody's using this named font, so don't have to tell any
@@ -858,13 +851,13 @@ UpdateDependentFonts(
cacheHashPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
while (cacheHashPtr != NULL) {
- for (fontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
+ for (fontPtr = Tcl_GetHashValue(cacheHashPtr);
fontPtr != NULL; fontPtr = fontPtr->nextPtr) {
if (fontPtr->namedHashPtr == namedHashPtr) {
TkpGetFontFromAttributes(fontPtr, tkwin, &nfPtr->fa);
- if (fiPtr->updatePending == 0) {
+ if (!fiPtr->updatePending) {
fiPtr->updatePending = 1;
- Tcl_DoWhenIdle(TheWorldHasChanged, (ClientData) fiPtr);
+ Tcl_DoWhenIdle(TheWorldHasChanged, fiPtr);
}
}
}
@@ -876,11 +869,9 @@ static void
TheWorldHasChanged(
ClientData clientData) /* Info about application's fonts. */
{
- TkFontInfo *fiPtr;
+ TkFontInfo *fiPtr = clientData;
- fiPtr = (TkFontInfo *) clientData;
fiPtr->updatePending = 0;
-
RecomputeWidgets(fiPtr->mainPtr->winPtr);
}
@@ -888,10 +879,11 @@ static void
RecomputeWidgets(
TkWindow *winPtr) /* Window to which command is sent. */
{
- Tk_ClassWorldChangedProc *proc;
- proc = Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc);
+ Tk_ClassWorldChangedProc *proc =
+ Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc);
+
if (proc != NULL) {
- (*proc)(winPtr->instanceData);
+ proc(winPtr->instanceData);
}
/*
@@ -949,21 +941,19 @@ TkCreateNamedFont(
const char *name, /* Name for the new named font. */
TkFontAttributes *faPtr) /* Attributes for the new named font. */
{
- TkFontInfo *fiPtr;
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
Tcl_HashEntry *namedHashPtr;
int isNew;
NamedFont *nfPtr;
- fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
-
namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &isNew);
-
if (!isNew) {
- nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
- if (nfPtr->deletePending == 0) {
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
+ if (!nfPtr->deletePending) {
if (interp) {
- Tcl_AppendResult(interp, "named font \"", name,
- "\" already exists", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "named font \"%s\" already exists", name));
+ Tcl_SetErrorCode(interp, "TK", "FONT", "EXISTS", NULL);
}
return TCL_ERROR;
}
@@ -980,7 +970,7 @@ TkCreateNamedFont(
return TCL_OK;
}
- nfPtr = (NamedFont *) ckalloc(sizeof(NamedFont));
+ nfPtr = ckalloc(sizeof(NamedFont));
nfPtr->deletePending = 0;
Tcl_SetHashValue(namedHashPtr, nfPtr);
nfPtr->fa = *faPtr;
@@ -1004,28 +994,27 @@ int
TkDeleteNamedFont(
Tcl_Interp *interp, /* Interp for error return (can be NULL). */
Tk_Window tkwin, /* A window associated with interp. */
- CONST char *name) /* Name for the new named font. */
+ const char *name) /* Name for the new named font. */
{
- TkFontInfo *fiPtr;
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
NamedFont *nfPtr;
Tcl_HashEntry *namedHashPtr;
- fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
-
namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, name);
if (namedHashPtr == NULL) {
if (interp) {
- Tcl_AppendResult(interp, "named font \"", name,
- "\" doesn't exist", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "named font \"%s\" doesn't exist", name));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", name, NULL);
}
return TCL_ERROR;
}
- nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
if (nfPtr->refCount != 0) {
nfPtr->deletePending = 1;
} else {
Tcl_DeleteHashEntry(namedHashPtr);
- ckfree((char *) nfPtr);
+ ckfree(nfPtr);
}
return TCL_OK;
}
@@ -1062,7 +1051,7 @@ Tk_GetFont(
Tk_Font tkfont;
Tcl_Obj *strPtr;
- strPtr = Tcl_NewStringObj((char *) string, -1);
+ strPtr = Tcl_NewStringObj(string, -1);
Tcl_IncrRefCount(strPtr);
tkfont = Tk_AllocFontFromObj(interp, tkwin, strPtr);
Tcl_DecrRefCount(strPtr);
@@ -1098,19 +1087,17 @@ Tk_AllocFontFromObj(
Tcl_Obj *objPtr) /* Object describing font, as: named font,
* native format, or parseable string. */
{
- TkFontInfo *fiPtr;
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
Tcl_HashEntry *cacheHashPtr, *namedHashPtr;
TkFont *fontPtr, *firstFontPtr, *oldFontPtr;
int isNew, descent;
NamedFont *nfPtr;
- fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
if (objPtr->typePtr != &tkFontObjType) {
SetFontFromAny(interp, objPtr);
}
- oldFontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1;
-
+ oldFontPtr = objPtr->internalRep.twoPtrValue.ptr1;
if (oldFontPtr != NULL) {
if (oldFontPtr->resourceRefCount == 0) {
/*
@@ -1118,7 +1105,7 @@ Tk_AllocFontFromObj(
* longer in use. Clear the reference.
*/
- FreeFontObjProc(objPtr);
+ FreeFontObj(objPtr);
oldFontPtr = NULL;
} else if (Tk_Screen(tkwin) == oldFontPtr->screen) {
oldFontPtr->resourceRefCount++;
@@ -1134,18 +1121,18 @@ Tk_AllocFontFromObj(
isNew = 0;
if (oldFontPtr != NULL) {
cacheHashPtr = oldFontPtr->cacheHashPtr;
- FreeFontObjProc(objPtr);
+ FreeFontObj(objPtr);
} else {
cacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache,
Tcl_GetString(objPtr), &isNew);
}
- firstFontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
+ firstFontPtr = Tcl_GetHashValue(cacheHashPtr);
for (fontPtr = firstFontPtr; (fontPtr != NULL);
fontPtr = fontPtr->nextPtr) {
if (Tk_Screen(tkwin) == fontPtr->screen) {
fontPtr->resourceRefCount++;
fontPtr->objRefCount++;
- objPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
return (Tk_Font) fontPtr;
}
}
@@ -1161,7 +1148,7 @@ Tk_AllocFontFromObj(
* Construct a font based on a named font.
*/
- nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
+ nfPtr = Tcl_GetHashValue(namedHashPtr);
nfPtr->refCount++;
fontPtr = TkpGetFontFromAttributes(NULL, tkwin, &nfPtr->fa);
@@ -1200,8 +1187,10 @@ Tk_AllocFontFromObj(
if (isNew) {
Tcl_DeleteHashEntry(cacheHashPtr);
}
- Tcl_AppendResult(interp, "failed to allocate font due to ",
- "internal system font engine problem", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "failed to allocate font due to internal system font engine"
+ " problem", -1));
+ Tcl_SetErrorCode(interp, "TK", "FONT", "INTERNAL_PROBLEM", NULL);
return NULL;
}
@@ -1253,7 +1242,7 @@ Tk_AllocFontFromObj(
}
}
- objPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
return (Tk_Font) fontPtr;
}
@@ -1278,7 +1267,8 @@ Tk_AllocFontFromObj(
Tk_Font
Tk_GetFontFromObj(
- Tk_Window tkwin, /* The window that the font will be used in. */
+ Tk_Window tkwin, /* The window that the font will be used
+ * in. */
Tcl_Obj *objPtr) /* The object from which to get the font. */
{
TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
@@ -1289,8 +1279,7 @@ Tk_GetFontFromObj(
SetFontFromAny(NULL, objPtr);
}
- fontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1;
-
+ fontPtr = objPtr->internalRep.twoPtrValue.ptr1;
if (fontPtr != NULL) {
if (fontPtr->resourceRefCount == 0) {
/*
@@ -1298,7 +1287,7 @@ Tk_GetFontFromObj(
* longer in use. Clear the reference.
*/
- FreeFontObjProc(objPtr);
+ FreeFontObj(objPtr);
fontPtr = NULL;
} else if (Tk_Screen(tkwin) == fontPtr->screen) {
return (Tk_Font) fontPtr;
@@ -1312,16 +1301,16 @@ Tk_GetFontFromObj(
if (fontPtr != NULL) {
hashPtr = fontPtr->cacheHashPtr;
- FreeFontObjProc(objPtr);
+ FreeFontObj(objPtr);
} else {
hashPtr = Tcl_FindHashEntry(&fiPtr->fontCache, Tcl_GetString(objPtr));
}
if (hashPtr != NULL) {
- for (fontPtr = (TkFont *) Tcl_GetHashValue(hashPtr); fontPtr != NULL;
+ for (fontPtr = Tcl_GetHashValue(hashPtr); fontPtr != NULL;
fontPtr = fontPtr->nextPtr) {
if (Tk_Screen(tkwin) == fontPtr->screen) {
fontPtr->objRefCount++;
- objPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
return (Tk_Font) fontPtr;
}
}
@@ -1363,7 +1352,7 @@ SetFontFromAny(
Tcl_GetString(objPtr);
typePtr = objPtr->typePtr;
if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- (*typePtr->freeIntRepProc)(objPtr);
+ typePtr->freeIntRepProc(objPtr);
}
objPtr->typePtr = &tkFontObjType;
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
@@ -1394,9 +1383,8 @@ const char *
Tk_NameOfFont(
Tk_Font tkfont) /* Font whose name is desired. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr = (TkFont *) tkfont;
- fontPtr = (TkFont *) tkfont;
return fontPtr->cacheHashPtr->key.string;
}
@@ -1421,13 +1409,12 @@ void
Tk_FreeFont(
Tk_Font tkfont) /* Font to be released. */
{
- TkFont *fontPtr, *prevPtr;
+ TkFont *fontPtr = (TkFont *) tkfont, *prevPtr;
NamedFont *nfPtr;
- if (tkfont == NULL) {
+ if (fontPtr == NULL) {
return;
}
- fontPtr = (TkFont *) tkfont;
fontPtr->resourceRefCount--;
if (fontPtr->resourceRefCount > 0) {
return;
@@ -1438,15 +1425,15 @@ Tk_FreeFont(
* the named font and free it if no-one else is using it.
*/
- nfPtr = (NamedFont *) Tcl_GetHashValue(fontPtr->namedHashPtr);
+ nfPtr = Tcl_GetHashValue(fontPtr->namedHashPtr);
nfPtr->refCount--;
- if ((nfPtr->refCount == 0) && (nfPtr->deletePending != 0)) {
+ if ((nfPtr->refCount == 0) && nfPtr->deletePending) {
Tcl_DeleteHashEntry(fontPtr->namedHashPtr);
- ckfree((char *) nfPtr);
+ ckfree(nfPtr);
}
}
- prevPtr = (TkFont *) Tcl_GetHashValue(fontPtr->cacheHashPtr);
+ prevPtr = Tcl_GetHashValue(fontPtr->cacheHashPtr);
if (prevPtr == fontPtr) {
if (fontPtr->nextPtr == NULL) {
Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);
@@ -1462,7 +1449,7 @@ Tk_FreeFont(
TkpDeleteFont(fontPtr);
if (fontPtr->objRefCount == 0) {
- ckfree((char *) fontPtr);
+ ckfree(fontPtr);
}
}
@@ -1496,7 +1483,7 @@ Tk_FreeFontFromObj(
/*
*---------------------------------------------------------------------------
*
- * FreeFontObjProc --
+ * FreeFontObjProc, FreeFontObj --
*
* This proc is called to release an object reference to a font. Called
* when the object's internal rep is released or when the cached fontPtr
@@ -1516,12 +1503,20 @@ static void
FreeFontObjProc(
Tcl_Obj *objPtr) /* The object we are releasing. */
{
- TkFont *fontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1;
+ FreeFontObj(objPtr);
+ objPtr->typePtr = NULL;
+}
+
+static void
+FreeFontObj(
+ Tcl_Obj *objPtr) /* The object we are releasing. */
+{
+ TkFont *fontPtr = objPtr->internalRep.twoPtrValue.ptr1;
if (fontPtr != NULL) {
fontPtr->objRefCount--;
if ((fontPtr->resourceRefCount == 0) && (fontPtr->objRefCount == 0)) {
- ckfree((char *) fontPtr);
+ ckfree(fontPtr);
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
}
}
@@ -1550,10 +1545,10 @@ DupFontObjProc(
Tcl_Obj *srcObjPtr, /* The object we are copying from. */
Tcl_Obj *dupObjPtr) /* The object we are copying to. */
{
- TkFont *fontPtr = (TkFont *) srcObjPtr->internalRep.twoPtrValue.ptr1;
+ TkFont *fontPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
dupObjPtr->typePtr = srcObjPtr->typePtr;
- dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
if (fontPtr != NULL) {
fontPtr->objRefCount++;
@@ -1584,9 +1579,8 @@ Tk_FontId(
Tk_Font tkfont) /* Font that is going to be selected into
* GC. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr = (TkFont *) tkfont;
- fontPtr = (TkFont *) tkfont;
return fontPtr->fid;
}
@@ -1617,9 +1611,8 @@ Tk_GetFontMetrics(
Tk_FontMetrics *fmPtr) /* Pointer to structure in which font metrics
* for tkfont will be stored. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr = (TkFont *) tkfont;
- fontPtr = (TkFont *) tkfont;
fmPtr->ascent = fontPtr->fm.ascent;
fmPtr->descent = fontPtr->fm.descent;
fmPtr->linespace = fontPtr->fm.ascent + fontPtr->fm.descent;
@@ -1659,13 +1652,12 @@ Tk_PostscriptFontName(
* which the name of the Postscript font that
* corresponds to tkfont will be appended. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr = (TkFont *) tkfont;
Tk_Uid family, weightString, slantString;
char *src, *dest;
int upper, len;
len = Tcl_DStringLength(dsPtr);
- fontPtr = (TkFont *) tkfont;
/*
* Convert the case-insensitive Tk_Font family name to the case-sensitive
@@ -1763,7 +1755,7 @@ Tk_PostscriptFontName(
slantString = NULL;
if (fontPtr->fa.slant == TK_FS_ROMAN) {
- ;
+ /* Do nothing */
} else if ((strcmp(family, "Helvetica") == 0)
|| (strcmp(family, "Courier") == 0)
|| (strcmp(family, "AvantGarde") == 0)) {
@@ -1891,19 +1883,17 @@ TkUnderlineCharsInContext(
int lastByte) /* Index of first byte after the last
* character. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr = (TkFont *) tkfont;
int startX, endX;
- fontPtr = (TkFont *) tkfont;
-
TkpMeasureCharsInContext(tkfont, string, numBytes, 0, firstByte, -1, 0,
&startX);
TkpMeasureCharsInContext(tkfont, string, numBytes, 0, lastByte, -1, 0,
&endX);
XFillRectangle(display, drawable, gc, x + startX,
- y + fontPtr->underlinePos, (unsigned int) (endX - startX),
- (unsigned int) fontPtr->underlineHeight);
+ y + fontPtr->underlinePos, (unsigned) (endX - startX),
+ (unsigned) fontPtr->underlineHeight);
}
/*
@@ -1954,7 +1944,7 @@ Tk_ComputeTextLayout(
int *widthPtr, /* Filled with width of string. */
int *heightPtr) /* Filled with height of string. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr = (TkFont *) tkfont;
const char *start, *end, *special;
int n, y, bytesThisChunk, maxChunks, curLine, layoutHeight;
int baseline, height, curX, newX, maxWidth, *lineLengths;
@@ -1965,7 +1955,6 @@ Tk_ComputeTextLayout(
Tcl_DStringInit(&lineBuffer);
- fontPtr = (TkFont *) tkfont;
if ((fontPtr == NULL) || (string == NULL)) {
if (widthPtr != NULL) {
*widthPtr = 0;
@@ -1989,8 +1978,8 @@ Tk_ComputeTextLayout(
maxChunks = 1;
- layoutPtr = (TextLayout *)
- ckalloc(sizeof(TextLayout) + (maxChunks-1) * sizeof(LayoutChunk));
+ layoutPtr = ckalloc(sizeof(TextLayout)
+ + (maxChunks-1) * sizeof(LayoutChunk));
layoutPtr->tkfont = tkfont;
layoutPtr->string = string;
layoutPtr->numChunks = 0;
@@ -2154,7 +2143,7 @@ Tk_ComputeTextLayout(
* on the next line. Otherwise "Hello" and "Hello\n" are the same height.
*/
- if ((layoutPtr->numChunks > 0) && ((flags & TK_IGNORE_NEWLINES) == 0)) {
+ if ((layoutPtr->numChunks > 0) && !(flags & TK_IGNORE_NEWLINES)) {
if (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\n') {
chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, 0, curX,
curX, baseline);
@@ -2243,11 +2232,10 @@ void
Tk_FreeTextLayout(
Tk_TextLayout textLayout) /* The text layout to be released. */
{
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) textLayout;
- layoutPtr = (TextLayout *) textLayout;
if (layoutPtr != NULL) {
- ckfree((char *) layoutPtr);
+ ckfree(layoutPtr);
}
}
@@ -2275,7 +2263,8 @@ void
Tk_DrawTextLayout(
Display *display, /* Display on which to draw. */
Drawable drawable, /* Window or pixmap in which to draw. */
- GC gc, /* Graphics context to use for drawing text. */
+ GC gc, /* Graphics context to use for drawing
+ * text. */
Tk_TextLayout layout, /* Layout information, from a previous call to
* Tk_ComputeTextLayout(). */
int x, int y, /* Upper-left hand corner of rectangle in
@@ -2287,13 +2276,11 @@ Tk_DrawTextLayout(
* draw from the given text item. A number < 0
* means to draw all characters. */
{
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) layout;
int i, numDisplayChars, drawX;
- const char *firstByte;
- const char *lastByte;
+ const char *firstByte, *lastByte;
LayoutChunk *chunkPtr;
- layoutPtr = (TextLayout *) layout;
if (layoutPtr == NULL) {
return;
}
@@ -2318,9 +2305,78 @@ Tk_DrawTextLayout(
numDisplayChars = lastChar;
}
lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
- Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont,
- firstByte, lastByte - firstByte,
- x + chunkPtr->x + drawX, y + chunkPtr->y);
+ Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte,
+ lastByte - firstByte, x+chunkPtr->x+drawX, y+chunkPtr->y);
+ }
+ firstChar -= chunkPtr->numChars;
+ lastChar -= chunkPtr->numChars;
+ if (lastChar <= 0) {
+ break;
+ }
+ chunkPtr++;
+ }
+}
+
+void
+TkDrawAngledTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing
+ * text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ double angle,
+ int firstChar, /* The index of the first character to draw
+ * from the given text item. 0 specfies the
+ * beginning. */
+ int lastChar) /* The index just after the last character to
+ * draw from the given text item. A number < 0
+ * means to draw all characters. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ int i, numDisplayChars, drawX;
+ const char *firstByte, *lastByte;
+ LayoutChunk *chunkPtr;
+ double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);
+
+ if (layoutPtr == NULL) {
+ return;
+ }
+
+ if (lastChar < 0) {
+ lastChar = 100000000;
+ }
+ chunkPtr = layoutPtr->chunks;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ numDisplayChars = chunkPtr->numDisplayChars;
+ if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {
+ double dx, dy;
+
+ if (firstChar <= 0) {
+ drawX = 0;
+ firstChar = 0;
+ firstByte = chunkPtr->start;
+ } else {
+ firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);
+ Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
+ firstByte - chunkPtr->start, -1, 0, &drawX);
+ }
+ if (lastChar < numDisplayChars) {
+ numDisplayChars = lastChar;
+ }
+ lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
+ dx = cosA * (chunkPtr->x + drawX) + sinA * (chunkPtr->y);
+ dy = -sinA * (chunkPtr->x + drawX) + cosA * (chunkPtr->y);
+ if (angle == 0.0) {
+ Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont,
+ firstByte, lastByte - firstByte,
+ (int)(x + dx), (int)(y + dy));
+ } else {
+ TkDrawAngledChars(display, drawable, gc, layoutPtr->tkfont,
+ firstByte, lastByte - firstByte, x+dx, y+dy, angle);
+ }
}
firstChar -= chunkPtr->numChars;
lastChar -= chunkPtr->numChars;
@@ -2366,18 +2422,79 @@ Tk_UnderlineTextLayout(
int underline) /* Index of the single character to underline,
* or -1 for no underline. */
{
- TextLayout *layoutPtr;
- TkFont *fontPtr;
int xx, yy, width, height;
if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)
&& (width != 0)) {
- layoutPtr = (TextLayout *) layout;
- fontPtr = (TkFont *) layoutPtr->tkfont;
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ TkFont *fontPtr = (TkFont *) layoutPtr->tkfont;
XFillRectangle(display, drawable, gc, x + xx,
y + yy + fontPtr->fm.ascent + fontPtr->underlinePos,
- (unsigned int) width, (unsigned int) fontPtr->underlineHeight);
+ (unsigned) width, (unsigned) fontPtr->underlineHeight);
+ }
+}
+
+void
+TkUnderlineAngledTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing
+ * text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ double angle,
+ int underline) /* Index of the single character to underline,
+ * or -1 for no underline. */
+{
+ int xx, yy, width, height;
+
+ if (angle == 0.0) {
+ Tk_UnderlineTextLayout(display, drawable, gc, layout, x,y, underline);
+ return;
+ }
+
+ if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)
+ && (width != 0)) {
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ TkFont *fontPtr = (TkFont *) layoutPtr->tkfont;
+ double sinA = sin(angle*PI/180), cosA = cos(angle*PI/180);
+ double dy = yy + fontPtr->fm.ascent + fontPtr->underlinePos;
+ XPoint points[5];
+
+ /*
+ * Note that we're careful to only round a double value once, which
+ * minimizes roundoff errors.
+ */
+
+ points[0].x = x + ROUND16(xx*cosA + dy*sinA);
+ points[0].y = y + ROUND16(dy*cosA - xx*sinA);
+ points[1].x = x + ROUND16(xx*cosA + dy*sinA + width*cosA);
+ points[1].y = y + ROUND16(dy*cosA - xx*sinA - width*sinA);
+ if (fontPtr->underlineHeight == 1) {
+ /*
+ * Thin underlines look better when rotated when drawn as a line
+ * rather than a rectangle; the rasterizer copes better.
+ */
+
+ XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin);
+ } else {
+ points[2].x = x + ROUND16(xx*cosA + dy*sinA + width*cosA
+ + fontPtr->underlineHeight*sinA);
+ points[2].y = y + ROUND16(dy*cosA - xx*sinA - width*sinA
+ + fontPtr->underlineHeight*cosA);
+ points[3].x = x + ROUND16(xx*cosA + dy*sinA
+ + fontPtr->underlineHeight*sinA);
+ points[3].y = y + ROUND16(dy*cosA - xx*sinA
+ + fontPtr->underlineHeight*cosA);
+ points[4].x = points[0].x;
+ points[4].y = points[0].y;
+ XFillPolygon(display, drawable, gc, points, 5, Complex,
+ CoordModeOrigin);
+ XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);
+ }
}
}
@@ -2421,7 +2538,7 @@ Tk_PointToChar(
* to the upper-left corner of the text
* layout. */
{
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) layout;
LayoutChunk *chunkPtr, *lastPtr;
TkFont *fontPtr;
int i, n, dummy, baseline, pos, numChars;
@@ -2439,7 +2556,6 @@ Tk_PointToChar(
* Find which line contains the point.
*/
- layoutPtr = (TextLayout *) layout;
fontPtr = (TkFont *) layoutPtr->tkfont;
lastPtr = chunkPtr = layoutPtr->chunks;
numChars = 0;
@@ -2486,8 +2602,7 @@ Tk_PointToChar(
return numChars;
}
n = Tk_MeasureChars((Tk_Font) fontPtr, chunkPtr->start,
- chunkPtr->numBytes, x - chunkPtr->x,
- 0, &dummy);
+ chunkPtr->numBytes, x - chunkPtr->x, 0, &dummy);
return numChars + Tcl_NumUtfChars(chunkPtr->start, n);
}
numChars += chunkPtr->numChars;
@@ -2570,7 +2685,7 @@ Tk_CharBbox(
* bounding box for the character specified by
* index, if non-NULL. */
{
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) layout;
LayoutChunk *chunkPtr;
int i, x = 0, w;
Tk_Font tkfont;
@@ -2581,7 +2696,6 @@ Tk_CharBbox(
return 0;
}
- layoutPtr = (TextLayout *) layout;
chunkPtr = layoutPtr->chunks;
tkfont = layoutPtr->tkfont;
fontPtr = (TkFont *) tkfont;
@@ -2682,11 +2796,10 @@ Tk_DistanceToTextLayout(
* (in pixels). */
{
int i, x1, x2, y1, y2, xDiff, yDiff, dist, minDist, ascent, descent;
+ TextLayout *layoutPtr = (TextLayout *) layout;
LayoutChunk *chunkPtr;
- TextLayout *layoutPtr;
TkFont *fontPtr;
- layoutPtr = (TextLayout *) layout;
fontPtr = (TkFont *) layoutPtr->tkfont;
ascent = fontPtr->fm.ascent;
descent = fontPtr->fm.descent;
@@ -2770,7 +2883,7 @@ Tk_IntersectTextLayout(
* rectangular area, in pixels. */
{
int result, i, x1, y1, x2, y2;
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) layout;
LayoutChunk *chunkPtr;
TkFont *fontPtr;
int left, top, right, bottom;
@@ -2782,7 +2895,6 @@ Tk_IntersectTextLayout(
* and see if they were all inside or all outside.
*/
- layoutPtr = (TextLayout *) layout;
chunkPtr = layoutPtr->chunks;
fontPtr = (TkFont *) layoutPtr->tkfont;
@@ -2793,10 +2905,11 @@ Tk_IntersectTextLayout(
result = 0;
for (i = 0; i < layoutPtr->numChunks; i++) {
- if (chunkPtr->start[0] == '\n') {
+ if ((chunkPtr->start[0] == '\n') || (chunkPtr->numBytes == 0)) {
/*
- * Newline characters are not counted when computing area
- * intersection (but tab characters would still be considered).
+ * Newline characters and empty chunks are not counted when
+ * computing area intersection (but tab characters would still be
+ * considered).
*/
chunkPtr++;
@@ -2830,6 +2943,263 @@ Tk_IntersectTextLayout(
/*
*---------------------------------------------------------------------------
*
+ * TkIntersectAngledTextLayout --
+ *
+ * Determines whether a text layout that has been turned by an angle
+ * about its top-left coordinae lies entirely inside, entirely outside,
+ * or overlaps a given rectangle. Non-displaying space characters that
+ * occur at the end of individual lines in the text layout are ignored
+ * for intersection calculations.
+ *
+ * Results:
+ * The return value is -1 if the text layout is entirely outside of the
+ * rectangle, 0 if it overlaps, and 1 if it is entirely inside of the
+ * rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static inline int
+PointInQuadrilateral(
+ double qx[],
+ double qy[],
+ double x,
+ double y)
+{
+ int i;
+
+ for (i=0 ; i<4 ; i++) {
+ double sideDX = qx[(i+1)%4] - qx[i];
+ double sideDY = qy[(i+1)%4] - qy[i];
+ double dx = x - qx[i];
+ double dy = y - qy[i];
+
+ if (sideDX*dy < sideDY*dx) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static inline int
+sign(
+ double value)
+{
+ return (value < 0.0) ? -1 : (value > 0.0) ? 1 : 0;
+}
+
+static inline int
+SidesIntersect(
+ double ax1, double ay1, double ax2, double ay2,
+ double bx1, double by1, double bx2, double by2)
+{
+#if 0
+/* http://www.freelunchdesign.com/cgi-bin/codwiki.pl?DiscussionTopics/CollideMeUpBaby */
+
+ double a1, b1, c1, a2, b2, c2, r1, r2, r3, r4, denom;
+
+ a1 = ay2 - ay1;
+ b1 = ax1 - ax2;
+ c1 = (ax2 * ay1) - (ax1 * ay2);
+ r3 = (a1 * bx1) + (b1 * by1) + c1;
+ r4 = (a1 * bx2) + (b1 * by2) + c1;
+ if ((r3 != 0.0) && (r4 != 0.0) && (r3*r4 > 0.0)) {
+ return 0;
+ }
+
+ a2 = by2 - by1;
+ b2 = bx1 - bx2;
+ c2 = (bx2 * by1) - (bx1 * by2);
+ r1 = (a2 * ax1) + (b2 * ay1) + c2;
+ r2 = (a2 * ax2) + (b2 * ay2) + c2;
+ if ((r1 != 0.0) && (r2 != 0.0) && (r1*r2 > 0.0)) {
+ return 0;
+ }
+
+ denom = (a1 * b2) - (a2 * b1);
+ return (denom != 0.0);
+#else
+ /*
+ * A more efficient version. Two line segments intersect if, when seen
+ * from the perspective of one line, the two endpoints of the other
+ * segment lie on opposite sides of the line, and vice versa. "Lie on
+ * opposite sides" is computed by taking the cross products and seeing if
+ * they are of opposite signs.
+ */
+
+ double dx, dy, dx1, dy1;
+
+ dx = ax2 - ax1;
+ dy = ay2 - ay1;
+ dx1 = bx1 - ax1;
+ dy1 = by1 - ay1;
+ if ((dx*dy1-dy*dx1 > 0.0) == (dx*(by2-ay1)-dy*(bx2-ax1) > 0.0)) {
+ return 0;
+ }
+ dx = bx2 - bx1;
+ dy = by2 - by1;
+ if ((dy*dx1-dx*dy1 > 0.0) == (dx*(ay2-by1)-dy*(ax2-bx1) > 0.0)) {
+ return 0;
+ }
+ return 1;
+#endif
+}
+
+int
+TkIntersectAngledTextLayout(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner, in pixels, of
+ * rectangular area to compare with text
+ * layout. Coordinates are with respect to the
+ * upper-left hand corner of the text layout
+ * itself. */
+ int width, int height, /* The width and height of the above
+ * rectangular area, in pixels. */
+ double angle)
+{
+ int i, x1, y1, x2, y2;
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ TkFont *fontPtr;
+ double c = cos(angle * PI/180.0), s = sin(angle * PI/180.0);
+ double rx[4], ry[4];
+
+ if (angle == 0.0) {
+ return Tk_IntersectTextLayout(layout, x, y, width, height);
+ }
+
+ /*
+ * Compute the coordinates of the rectangle, rotated into text layout
+ * space.
+ */
+
+ rx[0] = x*c - y*s;
+ ry[0] = y*c + x*s;
+ rx[1] = (x+width)*c - y*s;
+ ry[1] = y*c + (x+width)*s;
+ rx[2] = (x+width)*c - (y+height)*s;
+ ry[2] = (y+height)*c + (x+width)*s;
+ rx[3] = x*c - (y+height)*s;
+ ry[3] = (y+height)*c + x*s;
+
+ /*
+ * Want to know if all chunks are inside the rectangle, or if there is any
+ * overlap. First, we check to see if all chunks are inside; if and only
+ * if they are, we're in the "inside" case.
+ */
+
+ layoutPtr = (TextLayout *) layout;
+ chunkPtr = layoutPtr->chunks;
+ fontPtr = (TkFont *) layoutPtr->tkfont;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+ if ( !PointInQuadrilateral(rx, ry, x1, y1) ||
+ !PointInQuadrilateral(rx, ry, x2, y1) ||
+ !PointInQuadrilateral(rx, ry, x2, y2) ||
+ !PointInQuadrilateral(rx, ry, x1, y2)) {
+ goto notInside;
+ }
+ }
+ return 1;
+
+ /*
+ * Next, check to see if all the points of the rectangle are inside a
+ * single chunk; if they are, we're in an "overlap" case.
+ */
+
+ notInside:
+ chunkPtr = layoutPtr->chunks;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ double cx[4], cy[4];
+
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ cx[0] = cx[3] = chunkPtr->x;
+ cy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent;
+ cx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth;
+ cy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent;
+ if ( !PointInQuadrilateral(cx, cy, rx[0], ry[0]) ||
+ !PointInQuadrilateral(cx, cy, rx[1], ry[1]) ||
+ !PointInQuadrilateral(cx, cy, rx[2], ry[2]) ||
+ !PointInQuadrilateral(cx, cy, rx[3], ry[3])) {
+ goto notReverseInside;
+ }
+ }
+ return 0;
+
+ /*
+ * If we're overlapping now, we must be partially in and out of at least
+ * one chunk. If that is the case, there must be one line segment of the
+ * rectangle that is touching or crossing a line segment of a chunk.
+ */
+
+ notReverseInside:
+ chunkPtr = layoutPtr->chunks;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ int j;
+
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+
+ for (j=0 ; j<4 ; j++) {
+ int k = (j+1) % 4;
+
+ if ( SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y1, x2,y1) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y1, x2,y2) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y2, x1,y2) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y2, x1,y1)) {
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * They must be wholly non-overlapping.
+ */
+
+ return -1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
* Tk_TextLayoutToPostscript --
*
* Outputs the contents of a text layout in Postscript format. The set of
@@ -2870,112 +3240,93 @@ Tk_TextLayoutToPostscript(
Tcl_Interp *interp, /* Filled with Postscript code. */
Tk_TextLayout layout) /* The layout to be rendered. */
{
-#define MAXUSE 128
- char buf[MAXUSE+30], uindex[5] = "\0\0\0\0", one_char[5];
- LayoutChunk *chunkPtr;
- int i, j, used, c, baseline, charsize;
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ LayoutChunk *chunkPtr = layoutPtr->chunks;
+ int baseline = chunkPtr->y;
+ Tcl_Obj *psObj = Tcl_NewObj();
+ int i, j, len;
+ const char *p, *glyphname;
+ char uindex[5], c, *ps;
Tcl_UniChar ch;
- const char *p, *last_p, *glyphname;
- TextLayout *layoutPtr;
- int bytecount=0;
- layoutPtr = (TextLayout *) layout;
- chunkPtr = layoutPtr->chunks;
- baseline = chunkPtr->y;
- used = 0;
- buf[used++] = '[';
- buf[used++] = '(';
- for (i = 0; i < layoutPtr->numChunks; i++) {
+ Tcl_AppendToObj(psObj, "[(", -1);
+ for (i = 0; i < layoutPtr->numChunks; i++, chunkPtr++) {
if (baseline != chunkPtr->y) {
- buf[used++] = ')';
- buf[used++] = ']';
- buf[used++] = '\n';
- buf[used++] = '[';
- buf[used++] = '(';
+ Tcl_AppendToObj(psObj, ")]\n[(", -1);
baseline = chunkPtr->y;
}
if (chunkPtr->numDisplayChars <= 0) {
if (chunkPtr->start[0] == '\t') {
- buf[used++] = '\\';
- buf[used++] = 't';
+ Tcl_AppendToObj(psObj, "\\t", -1);
}
- } else {
- p = chunkPtr->start;
- for (j = 0; j < chunkPtr->numDisplayChars; j++) {
+ continue;
+ }
+
+ for (p=chunkPtr->start, j=0; j<chunkPtr->numDisplayChars; j++) {
+ /*
+ * INTL: We only handle symbols that have an encoding as a glyph
+ * from the standard set defined by Adobe. The rest get punted.
+ * Eventually this should be revised to handle more sophsticiated
+ * international postscript fonts.
+ */
+
+ p += Tcl_UtfToUniChar(p, &ch);
+ if ((ch == '(') || (ch == ')') || (ch == '\\') || (ch < 0x20)) {
/*
- * INTL: For now we just treat the characters as binary data
- * and display the lower byte. Eventually this should be
- * revised to handle international postscript fonts.
+ * Tricky point: the "03" is necessary in the sprintf below,
+ * so that a full three digits of octal are always generated.
+ * Without the "03", a number following this sequence could be
+ * interpreted by Postscript as part of this sequence.
*/
- last_p = p;
- p += (charsize = Tcl_UtfToUniChar(p,&ch));
- Tcl_UtfToExternal(interp, NULL, last_p, charsize, 0, NULL,
- one_char, 4, NULL, &bytecount, NULL);
- if (bytecount == 1) {
- c = UCHAR(one_char[0]);
- /* c = UCHAR( ch & 0xFF) */;
- if ((c == '(') || (c == ')') || (c == '\\') || (c < 0x20)
- || (c >= UCHAR(0x7f))) {
- /*
- * Tricky point: the "03" is necessary in the sprintf
- * below, so that a full three digits of octal are
- * always generated. Without the "03", a number
- * following this sequence could be interpreted by
- * Postscript as part of this sequence.
- */
+ Tcl_AppendPrintfToObj(psObj, "\\%03o", ch);
+ continue;
+ } else if (ch <= 0x7f) {
+ /*
+ * Normal ASCII character.
+ */
- sprintf(buf + used, "\\%03o", c);
- used += 4;
- } else {
- buf[used++] = c;
- }
- } else {
+ c = (char) ch;
+ Tcl_AppendToObj(psObj, &c, 1);
+ continue;
+ }
+
+ /*
+ * This character doesn't belong to the ASCII character set, so we
+ * use the full glyph name.
+ */
+
+ sprintf(uindex, "%04X", ch); /* endianness? */
+ glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", uindex, 0);
+ if (glyphname) {
+ ps = Tcl_GetStringFromObj(psObj, &len);
+ if (ps[len-1] == '(') {
/*
- * This character doesn't belong to system character set.
- * So, we must use full glyph name.
+ * In-place edit. Ewww!
*/
- sprintf(uindex, "%04X", ch); /* endianness? */
- glyphname = Tcl_GetVar2(interp,"::tk::psglyphs",uindex,0);
- if (glyphname) {
- if (used > 0 && buf [used-1] == '(') {
- --used;
- } else {
- buf[used++] = ')';
- }
- buf[used++] = '/';
- while ((*glyphname) && (used < (MAXUSE+27))) {
- buf[used++] = *glyphname++ ;
- }
- buf[used++] = '(';
- }
-
- }
- if (used >= MAXUSE) {
- buf[used] = '\0';
- Tcl_AppendResult(interp, buf, NULL);
- used = 0;
+ ps[len-1] = '/';
+ } else {
+ Tcl_AppendToObj(psObj, ")/", -1);
}
- }
- }
- if (used >= MAXUSE) {
- /*
- * If there are a whole bunch of returns or tabs in a row, then
- * buf[] could get filled up.
- */
+ Tcl_AppendToObj(psObj, glyphname, -1);
+ Tcl_AppendToObj(psObj, "(", -1);
+ } else {
+ /*
+ * No known mapping for the character into the space of
+ * PostScript glyphs. Ignore it. :-(
+ */
- buf[used] = '\0';
- Tcl_AppendResult(interp, buf, NULL);
- used = 0;
+#ifdef TK_DEBUG_POSTSCRIPT_OUTPUT
+ fprintf(stderr, "Warning: no mapping to PostScript "
+ "glyphs for \\u%04x\n", ch);
+#endif
+ }
}
- chunkPtr++;
}
- buf[used++] = ')';
- buf[used++] = ']';
- buf[used++] = '\n';
- buf[used] = '\0';
- Tcl_AppendResult(interp, buf, NULL);
+ Tcl_AppendToObj(psObj, ")]\n", -1);
+ Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
+ Tcl_DecrRefCount(psObj);
}
/*
@@ -3011,7 +3362,7 @@ ConfigAttributesObj(
{
int i, n, index;
Tcl_Obj *optionPtr, *valuePtr;
- char *value;
+ const char *value;
for (i = 0; i < objc; i += 2) {
optionPtr = objv[i];
@@ -3029,8 +3380,10 @@ ConfigAttributesObj(
*/
if (interp != NULL) {
- Tcl_AppendResult(interp, "value for \"",
- Tcl_GetString(optionPtr), "\" option missing", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" option missing",
+ Tcl_GetString(optionPtr)));
+ Tcl_SetErrorCode(interp, "TK", "FONT", "NO_ATTRIBUTE", NULL);
}
return TCL_ERROR;
}
@@ -3110,9 +3463,7 @@ GetAttributeInfoObj(
{
int i, index, start, end;
const char *str;
- Tcl_Obj *optionPtr, *valuePtr, *resultPtr;
-
- resultPtr = Tcl_GetObjResult(interp);
+ Tcl_Obj *valuePtr, *resultPtr = NULL;
start = 0;
end = FONT_NUMFIELDS;
@@ -3126,6 +3477,9 @@ GetAttributeInfoObj(
}
valuePtr = NULL;
+ if (objPtr == NULL) {
+ resultPtr = Tcl_NewObj();
+ }
for (i = start; i < end; i++) {
switch (i) {
case FONT_FAMILY:
@@ -3159,10 +3513,11 @@ GetAttributeInfoObj(
Tcl_SetObjResult(interp, valuePtr);
return TCL_OK;
}
- optionPtr = Tcl_NewStringObj(fontOpt[i], -1);
- Tcl_ListObjAppendElement(NULL, resultPtr, optionPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(fontOpt[i], -1));
Tcl_ListObjAppendElement(NULL, resultPtr, valuePtr);
}
+ Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -3204,7 +3559,7 @@ ParseFontNameObj(
char *dash;
int objc, result, i, n;
Tcl_Obj **objv;
- char *string;
+ const char *string;
TkInitFontAttributes(faPtr);
@@ -3222,7 +3577,7 @@ ParseFontNameObj(
}
dash = strchr(string + 1, '-');
if ((dash != NULL)
- && (!isspace(UCHAR(dash[-1])))) { /* INTL: ISO space */
+ && !isspace(UCHAR(dash[-1]))) { /* INTL: ISO space */
goto xlfd;
}
@@ -3270,8 +3625,9 @@ ParseFontNameObj(
if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK)
|| (objc < 1)) {
if (interp != NULL) {
- Tcl_AppendResult(interp, "font \"", string, "\" doesn't exist",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "font \"%s\" doesn't exist", string));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL);
}
return TCL_ERROR;
}
@@ -3318,8 +3674,10 @@ ParseFontNameObj(
*/
if (interp != NULL) {
- Tcl_AppendResult(interp, "unknown font style \"",
- Tcl_GetString(objv[i]), "\"", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown font style \"%s\"", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT_STYLE",
+ Tcl_GetString(objv[i]), NULL);
}
return TCL_ERROR;
}
@@ -3367,7 +3725,7 @@ NewChunk(
if (layoutPtr->numChunks == maxChunks) {
maxChunks *= 2;
s = sizeof(TextLayout) + ((maxChunks - 1) * sizeof(LayoutChunk));
- layoutPtr = (TextLayout *) ckrealloc((char *) layoutPtr, s);
+ layoutPtr = ckrealloc(layoutPtr, s);
*layoutPtrPtr = layoutPtr;
*maxPtr = maxChunks;
@@ -3439,7 +3797,7 @@ TkFontParseXLFD(
}
Tcl_DStringInit(&ds);
- Tcl_DStringAppend(&ds, (char *) str, -1);
+ Tcl_DStringAppend(&ds, str, -1);
src = Tcl_DStringValue(&ds);
field[0] = src;
@@ -3472,7 +3830,7 @@ TkFontParseXLFD(
* parsed set of attributes)".
*/
- if ((i > XLFD_ADD_STYLE) && (FieldSpecified(field[XLFD_ADD_STYLE]))) {
+ if ((i > XLFD_ADD_STYLE) && FieldSpecified(field[XLFD_ADD_STYLE])) {
if (atoi(field[XLFD_ADD_STYLE]) != 0) {
for (j = XLFD_NUMFIELDS - 1; j >= XLFD_ADD_STYLE; j--) {
field[j + 1] = field[j];
@@ -3701,7 +4059,6 @@ TkFontGetPoints(
* platform expects when asking for the font.
*
* Results:
-
* As above. The return value is NULL if the font name has no aliases.
*
* Side effects:
@@ -3710,7 +4067,7 @@ TkFontGetPoints(
*-------------------------------------------------------------------------
*/
-char **
+const char *const *
TkFontGetAliasList(
const char *faceName) /* Font name to test for aliases. */
{
@@ -3743,7 +4100,7 @@ TkFontGetAliasList(
*-------------------------------------------------------------------------
*/
-char ***
+const char *const *const *
TkFontGetFallbacks(void)
{
return fontFallbacks;
@@ -3768,7 +4125,7 @@ TkFontGetFallbacks(void)
*-------------------------------------------------------------------------
*/
-char **
+const char *const *
TkFontGetGlobalClass(void)
{
return globalFontClass;
@@ -3791,7 +4148,7 @@ TkFontGetGlobalClass(void)
*-------------------------------------------------------------------------
*/
-char **
+const char *const *
TkFontGetSymbolClass(void)
{
return symbolClass;
@@ -3819,7 +4176,7 @@ Tcl_Obj *
TkDebugFont(
Tk_Window tkwin, /* The window in which the font will be used
* (not currently used). */
- char *name) /* Name of the desired color. */
+ const char *name) /* Name of the desired color. */
{
TkFont *fontPtr;
Tcl_HashEntry *hashPtr;
@@ -3829,7 +4186,7 @@ TkDebugFont(
hashPtr = Tcl_FindHashEntry(
&((TkWindow *) tkwin)->mainPtr->fontInfoPtr->fontCache, name);
if (hashPtr != NULL) {
- fontPtr = (TkFont *) Tcl_GetHashValue(hashPtr);
+ fontPtr = Tcl_GetHashValue(hashPtr);
if (fontPtr == NULL) {
Tcl_Panic("TkDebugFont found empty hash table entry");
}
@@ -3871,12 +4228,11 @@ TkFontGetFirstTextLayout(
Tk_Font *font,
char *dst)
{
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) layout;
LayoutChunk *chunkPtr;
int numBytesInChunk;
- layoutPtr = (TextLayout *)layout;
- if ((layoutPtr==NULL) || (layoutPtr->numChunks==0)
+ if ((layoutPtr == NULL) || (layoutPtr->numChunks == 0)
|| (layoutPtr->chunks->numDisplayChars <= 0)) {
dst[0] = '\0';
return 0;