summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkObj.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/generic/tkObj.c b/generic/tkObj.c
index 47a3201..4d3e045 100644
--- a/generic/tkObj.c
+++ b/generic/tkObj.c
@@ -40,6 +40,19 @@ typedef struct PixelRep {
((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2)
/*
+ * One of these structures is created per thread to store thread-specific
+ * data. In this case, it is used to contain references to selected
+ * Tcl_ObjTypes that we can use as screen distances without conversion. The
+ * "dataKey" below is used to locate the ThreadSpecificData for the current
+ * thread.
+ */
+
+typedef struct {
+ const Tcl_ObjType *doubleTypePtr;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
* The following structure is the internal representation for mm objects.
*/
@@ -73,6 +86,7 @@ static void DupWindowInternalRep(Tcl_Obj *srcPtr,Tcl_Obj*copyPtr);
static void FreeMMInternalRep(Tcl_Obj *objPtr);
static void FreePixelInternalRep(Tcl_Obj *objPtr);
static void FreeWindowInternalRep(Tcl_Obj *objPtr);
+static ThreadSpecificData *GetTypeCache(void);
static void UpdateStringOfMM(Tcl_Obj *objPtr);
static int SetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int SetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
@@ -122,6 +136,37 @@ static const Tcl_ObjType windowObjType = {
/*
*----------------------------------------------------------------------
*
+ * GetTypeCache --
+ *
+ * Get (and build if necessary) the cache of useful Tcl object types for
+ * comparisons in the conversion functions. This allows optimized checks
+ * for standard cases.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ThreadSpecificData *
+GetTypeCache(void)
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->doubleTypePtr == NULL) {
+ /* Smart initialization of doubleTypePtr without
+ * hash-table lookup or creating complete Tcl_Obj's */
+ Tcl_Obj obj;
+ obj.length = 3;
+ obj.bytes = (char *)"0.0";
+ obj.typePtr = NULL;
+ Tcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue);
+ tsdPtr->doubleTypePtr = obj.typePtr;
+ }
+ return tsdPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* GetPixelsFromObjEx --
*
* Attempt to return a pixel value from the Tcl object "objPtr". If the
@@ -386,13 +431,15 @@ SetPixelFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
Tcl_Obj *objPtr) /* The object to convert. */
{
+ ThreadSpecificData *typeCache = GetTypeCache();
const Tcl_ObjType *typePtr;
const char *string;
char *rest;
double d;
int i, units;
- if (Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) {
+ if (objPtr->typePtr != typeCache->doubleTypePtr
+ && Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) {
d = (double) units;
units = -1;
@@ -656,6 +703,7 @@ SetMMFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
Tcl_Obj *objPtr) /* The object to convert. */
{
+ ThreadSpecificData *typeCache = GetTypeCache();
const Tcl_ObjType *typePtr;
char *string;
char *rest;
@@ -663,7 +711,8 @@ SetMMFromAny(
int units;
MMRep *mmPtr;
- if (Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) {
+ if (objPtr->typePtr != typeCache->doubleTypePtr
+ && Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) {
d = (double) units;
units = -1;