summaryrefslogtreecommitdiffstats
path: root/generic/tkObj.c
diff options
context:
space:
mode:
authordonal.k.fellows@manchester.ac.uk <dkf>2011-11-01 22:46:40 (GMT)
committerdonal.k.fellows@manchester.ac.uk <dkf>2011-11-01 22:46:40 (GMT)
commit1ce0de581543e9c8a1a448b7f2fdde7178844294 (patch)
treec0f7aa3d90f6406a2d3698d15f89dd8e0737d304 /generic/tkObj.c
parent8a874b0a0498dc0fd953aebe6e59ce01b36c0bef (diff)
downloadtk-1ce0de581543e9c8a1a448b7f2fdde7178844294.zip
tk-1ce0de581543e9c8a1a448b7f2fdde7178844294.tar.gz
tk-1ce0de581543e9c8a1a448b7f2fdde7178844294.tar.bz2
* generic/tkObj.c (GetPixelsFromObjEx): [Bug 3431491]: Use a bit of
type hackery to allow numbers to be interpreted as coordinates (most notably on a canvas) without reinterpreting via a string.
Diffstat (limited to 'generic/tkObj.c')
-rw-r--r--generic/tkObj.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/generic/tkObj.c b/generic/tkObj.c
index d973bd4..cb222cb 100644
--- a/generic/tkObj.c
+++ b/generic/tkObj.c
@@ -39,6 +39,19 @@ typedef struct PixelRep {
#define GET_COMPLEXPIXEL(objPtr) \
((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 ThreadSpecificData {
+ Tcl_ObjType *doubleTypePtr;
+ Tcl_ObjType *intTypePtr;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* The following structure is the internal representation for mm objects.
@@ -157,6 +170,38 @@ GetPixelsFromObjEx(
1.0, 10.0, 25.4, 0.35278 /*25.4 / 72.0*/
};
+ /*
+ * Special hacks where the type of the object is known to be something
+ * that is just numeric and cannot require distance conversion. This pokes
+ * holes in Tcl's abstractions, but they are just for optimization, not
+ * semantics.
+ */
+
+ if (objPtr->typePtr != &pixelObjType) {
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->doubleTypePtr == NULL) {
+ tsdPtr->doubleTypePtr = Tcl_GetObjType("double");
+ tsdPtr->intTypePtr = Tcl_GetObjType("int");
+ }
+
+ if (objPtr->typePtr == tsdPtr->doubleTypePtr) {
+ (void) Tcl_GetDoubleFromObj(interp, objPtr, &d);
+ if (dblPtr != NULL) {
+ *dblPtr = d;
+ }
+ *intPtr = (int) d;
+ return TCL_OK;
+ } else if (objPtr->typePtr == tsdPtr->intTypePtr) {
+ (void) Tcl_GetIntFromObj(interp, objPtr, intPtr);
+ if (dblPtr) {
+ *dblPtr = (double) (*intPtr);
+ }
+ return TCL_OK;
+ }
+ }
+
retry:
if (objPtr->typePtr != &pixelObjType) {
result = SetPixelFromAny(interp, objPtr);
@@ -271,7 +316,7 @@ Tk_GetDoublePixelsFromObj(
if (result != TCL_OK) {
return result;
}
- if (!SIMPLE_PIXELREP(objPtr)) {
+ if (objPtr->typePtr == &pixelObjType && !SIMPLE_PIXELREP(objPtr)) {
PixelRep *pixelPtr;
pixelPtr = GET_COMPLEXPIXEL(objPtr);
if (pixelPtr->units >= 0) {