summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorfvogel <fvogelnew1@free.fr>2017-09-16 08:26:38 (GMT)
committerfvogel <fvogelnew1@free.fr>2017-09-16 08:26:38 (GMT)
commit28ecd1d8e1c3f719e76cf10280c207b62dcd3769 (patch)
tree4f94d2704659fb5c378b3792edb54a4db371a885 /generic
parent7cf5207818e3ecc3b7a6a03bcafafb755f693297 (diff)
parentaa02ff624c358037f14b1716057349f06634f5d1 (diff)
downloadtk-28ecd1d8e1c3f719e76cf10280c207b62dcd3769.zip
tk-28ecd1d8e1c3f719e76cf10280c207b62dcd3769.tar.gz
tk-28ecd1d8e1c3f719e76cf10280c207b62dcd3769.tar.bz2
Fix [3406785]: Incorrect coords rounding, pixel jump in drawing canvas items.
Diffstat (limited to 'generic')
-rw-r--r--generic/tkRectOval.c102
1 files changed, 97 insertions, 5 deletions
diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c
index 50b5f1a..4d48fe7 100644
--- a/generic/tkRectOval.c
+++ b/generic/tkRectOval.c
@@ -759,11 +759,103 @@ DisplayRectOval(
&x1, &y1);
Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3],
&x2, &y2);
- if (x2 <= x1) {
- x2 = x1+1;
- }
- if (y2 <= y1) {
- y2 = y1+1;
+ if (x2 == x1) {
+
+ /*
+ * The width of the bounding box corresponds to less than one pixel
+ * on screen. Adjustment is needed to avoid drawing attempts with zero
+ * width items (which would draw nothing). The bounding box spans
+ * either 1 or 2 pixels. Select which pixel will be drawn.
+ */
+
+ short ix1 = (short) (rectOvalPtr->bbox[0]);
+ short ix2 = (short) (rectOvalPtr->bbox[2]);
+
+ if (ix1 == ix2) {
+
+ /*
+ * x1 and x2 are "within the same pixel". Use this pixel.
+ * Note: the degenerated case (bbox[0]==bbox[2]) of a completely
+ * flat box results in arbitrary selection of the pixel at the
+ * right (with positive coordinate) or left (with negative
+ * coordinate) of the box. There is no "best choice" here.
+ */
+
+ if (ix1 > 0) {
+ x2 += 1;
+ } else {
+ x1 -= 1;
+ }
+ } else {
+
+ /*
+ * (x1,x2) span two pixels. Select the one with the larger
+ * covered "area".
+ */
+
+ if (ix1 > 0) {
+ if ((rectOvalPtr->bbox[2] - ix2) > (ix2 - rectOvalPtr->bbox[0])) {
+ x2 += 1;
+ } else {
+ x1 -= 1;
+ }
+ } else {
+ if ((rectOvalPtr->bbox[2] - ix1) > (ix1 - rectOvalPtr->bbox[0])) {
+ x2 += 1;
+ } else {
+ x1 -= 1;
+ }
+ }
+ }
+ }
+ if (y2 == y1) {
+
+ /*
+ * The height of the bounding box corresponds to less than one pixel
+ * on screen. Adjustment is needed to avoid drawing attempts with zero
+ * height items (which would draw nothing). The bounding box spans
+ * either 1 or 2 pixels. Select which pixel will be drawn.
+ */
+
+ short iy1 = (short) (rectOvalPtr->bbox[1]);
+ short iy2 = (short) (rectOvalPtr->bbox[3]);
+
+ if (iy1 == iy2) {
+
+ /*
+ * y1 and y2 are "within the same pixel". Use this pixel.
+ * Note: the degenerated case (bbox[1]==bbox[3]) of a completely
+ * flat box results in arbitrary selection of the pixel below
+ * (with positive coordinate) or above (with negative coordinate)
+ * the box. There is no "best choice" here.
+ */
+
+ if (iy1 > 0) {
+ y2 += 1;
+ } else {
+ y1 -= 1;
+ }
+ } else {
+
+ /*
+ * (y1,y2) span two pixels. Select the one with the larger
+ * covered "area".
+ */
+
+ if (iy1 > 0) {
+ if ((rectOvalPtr->bbox[3] - iy2) > (iy2 - rectOvalPtr->bbox[1])) {
+ y2 += 1;
+ } else {
+ y1 -= 1;
+ }
+ } else {
+ if ((rectOvalPtr->bbox[3] - iy1) > (iy1 - rectOvalPtr->bbox[1])) {
+ y2 += 1;
+ } else {
+ y1 -= 1;
+ }
+ }
+ }
}
/*