Skip to content

Commit a97f35e

Browse files
author
csaba
committed
Fix for [971a266013]: Xlib emulation for macOS causes many visual artifacts.
1 parent a2926cf commit a97f35e

2 files changed

Lines changed: 123 additions & 36 deletions

File tree

changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ to the userbase.
2020
- [nanosvg possible zero malloc on file error](https://github.com/memononen/nanosvg/pull/291)
2121
- [Scaling on aqua gets unexpectedly reset](https://core.tcl-lang.org/tk/tktview/fe932e)
2222
- [ttk::entry has a wrong background in clam theme and readonly state](https://core.tcl-lang.org/tk/tktview/2f8570)
23+
- [Xlib emulation for macOS causes many visual artifacts](https://core.tcl-lang.org/tk/tktview/971a26)
2324

2425
Release Tk 9.0.4 arises from the check-in with tag `core-9-0-4`.
2526

macosx/tkMacOSXDraw.c

Lines changed: 122 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -389,34 +389,65 @@ XDrawLines(
389389
{
390390
MacDrawable *macWin = (MacDrawable *)d;
391391
TkMacOSXDrawingContext dc;
392-
int i, lw = gc->line_width;
393392

394-
if (npoints < 2) {
393+
if (npoints < 2 || (mode != CoordModeOrigin && mode != CoordModePrevious)) {
395394
return BadValue;
396395
}
397396

398397
LastKnownRequestProcessed(display)++;
399398
if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
400399
return BadDrawable;
401400
}
401+
402402
if (dc.context) {
403-
double prevx, prevy;
404-
double o = (lw % 2) ? .5 : 0;
403+
double o = (gc->line_width % 2) ? .5 : 0;
404+
short x0 = points[0].x, y0 = points[0].y;
405+
short x1 = (mode == CoordModeOrigin) ? points[1].x : x0 + points[1].x;
406+
short y1 = (mode == CoordModeOrigin) ? points[1].y : y0 + points[1].y;
407+
double prevx = macWin->xOff + x0 + o, prevy = macWin->yOff + y0 + o;
408+
int i;
405409

406410
CGContextBeginPath(dc.context);
407-
prevx = macWin->xOff + points[0].x + o;
408-
prevy = macWin->yOff + points[0].y + o;
411+
if (y1 == y0) { /* horiz. line */
412+
if (x0 <= x1) {
413+
prevx = macWin->xOff + x0;
414+
} else {
415+
prevx = macWin->xOff + x0 + 1;
416+
}
417+
} else if (x1 == x0) { /* vert. line */
418+
if (y0 <= y1) {
419+
prevy = macWin->yOff + y0;
420+
} else {
421+
prevy = macWin->yOff + y0 + 1;
422+
}
423+
}
409424
CGContextMoveToPoint(dc.context, prevx, prevy);
425+
410426
for (i = 1; i < npoints; i++) {
411-
if (mode == CoordModeOrigin) {
412-
CGContextAddLineToPoint(dc.context,
413-
macWin->xOff + points[i].x + o,
414-
macWin->yOff + points[i].y + o);
415-
} else {
416-
prevx += points[i].x;
417-
prevy += points[i].y;
418-
CGContextAddLineToPoint(dc.context, prevx, prevy);
427+
double nextx, nexty;
428+
429+
x1 = (mode == CoordModeOrigin) ? points[i].x : x0 + points[i].x;
430+
y1 = (mode == CoordModeOrigin) ? points[i].y : y0 + points[i].y;
431+
nextx = macWin->xOff + x1 + o;
432+
nexty = macWin->yOff + y1 + o;
433+
434+
if (i == npoints-1) {
435+
if (y1 == y0) { /* horiz. line */
436+
if (x0 <= x1) {
437+
nextx = macWin->xOff + x1 + 1;
438+
} else {
439+
nextx = macWin->xOff + x1;
440+
}
441+
} else if (x1 == x0) { /* vert. line */
442+
if (y0 <= y1) {
443+
nexty = macWin->yOff + y1 + 1;
444+
} else {
445+
nexty = macWin->yOff + y1;
446+
}
447+
}
419448
}
449+
CGContextAddLineToPoint(dc.context, nextx, nexty);
450+
x0 = x1; y0 = y1;
420451
}
421452

422453
/*
@@ -425,8 +456,7 @@ XDrawLines(
425456
* this needs telling CoreGraphics that the path is closed.
426457
*/
427458

428-
if ((points[0].x == points[npoints-1].x) &&
429-
(points[0].y == points[npoints-1].y)) {
459+
if (points[0].x == x1 && points[0].y == y1) {
430460
CGContextClosePath(dc.context);
431461
}
432462
CGContextStrokePath(dc.context);
@@ -461,23 +491,43 @@ XDrawSegments(
461491
{
462492
MacDrawable *macWin = (MacDrawable *)d;
463493
TkMacOSXDrawingContext dc;
464-
int i, lw = gc->line_width;
465494

466495
LastKnownRequestProcessed(display)++;
467496
if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
468497
return BadDrawable;
469498
}
499+
470500
if (dc.context) {
471-
double o = (lw % 2) ? .5 : 0;
501+
int i;
502+
double o = (gc->line_width % 2) ? .5 : 0;
472503

473504
for (i = 0; i < nsegments; i++) {
505+
double prevx = macWin->xOff + segments[i].x1 + o;
506+
double prevy = macWin->yOff + segments[i].y1 + o;
507+
double nextx = macWin->xOff + segments[i].x2 + o;
508+
double nexty = macWin->yOff + segments[i].y2 + o;
509+
510+
if (segments[i].y2 == segments[i].y1) { /* horiz. line */
511+
if (segments[i].x1 <= segments[i].x2) {
512+
prevx = macWin->xOff + segments[i].x1;
513+
nextx = macWin->xOff + segments[i].x2 + 1;
514+
} else {
515+
prevx = macWin->xOff + segments[i].x1 + 1;
516+
nextx = macWin->xOff + segments[i].x2;
517+
}
518+
} else if (segments[i].x2 == segments[i].x1) { /* vert. line */
519+
if (segments[i].y1 <= segments[i].y2) {
520+
prevy = macWin->yOff + segments[i].y1;
521+
nexty = macWin->yOff + segments[i].y2 + 1;
522+
} else {
523+
prevy = macWin->yOff + segments[i].y1 + 1;
524+
nexty = macWin->yOff + segments[i].y2;
525+
}
526+
}
527+
474528
CGContextBeginPath(dc.context);
475-
CGContextMoveToPoint(dc.context,
476-
macWin->xOff + segments[i].x1 + o,
477-
macWin->yOff + segments[i].y1 + o);
478-
CGContextAddLineToPoint(dc.context,
479-
macWin->xOff + segments[i].x2 + o,
480-
macWin->yOff + segments[i].y2 + o);
529+
CGContextMoveToPoint(dc.context, prevx, prevy);
530+
CGContextAddLineToPoint(dc.context, nextx, nexty);
481531
CGContextStrokePath(dc.context);
482532
}
483533
}
@@ -513,31 +563,67 @@ XFillPolygon(
513563
{
514564
MacDrawable *macWin = (MacDrawable *)d;
515565
TkMacOSXDrawingContext dc;
516-
int i;
566+
567+
if (npoints < 2 || (mode != CoordModeOrigin && mode != CoordModePrevious)) {
568+
return BadValue;
569+
}
517570

518571
LastKnownRequestProcessed(display)++;
519572
if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
520573
return BadDrawable;
521574
}
575+
522576
if (dc.context) {
523-
double prevx, prevy;
524577
double o = (gc->line_width % 2) ? .5 : 0;
578+
short x0 = points[0].x, y0 = points[0].y;
579+
short x1 = (mode == CoordModeOrigin) ? points[1].x : x0 + points[1].x;
580+
short y1 = (mode == CoordModeOrigin) ? points[1].y : y0 + points[1].y;
581+
double prevx = macWin->xOff + x0 + o, prevy = macWin->yOff + y0 + o;
582+
int i;
525583

526584
CGContextBeginPath(dc.context);
527-
prevx = macWin->xOff + points[0].x + o;
528-
prevy = macWin->yOff + points[0].y + o;
585+
if (y1 == y0) { /* horiz. line */
586+
if (x0 <= x1) {
587+
prevx = macWin->xOff + x0;
588+
} else {
589+
prevx = macWin->xOff + x0 + 1;
590+
}
591+
} else if (x1 == x0) { /* vert. line */
592+
if (y0 <= y1) {
593+
prevy = macWin->yOff + y0;
594+
} else {
595+
prevy = macWin->yOff + y0 + 1;
596+
}
597+
}
529598
CGContextMoveToPoint(dc.context, prevx, prevy);
599+
530600
for (i = 1; i < npoints; i++) {
531-
if (mode == CoordModeOrigin) {
532-
CGContextAddLineToPoint(dc.context,
533-
macWin->xOff + points[i].x + o,
534-
macWin->yOff + points[i].y + o);
535-
} else {
536-
prevx += points[i].x;
537-
prevy += points[i].y;
538-
CGContextAddLineToPoint(dc.context, prevx, prevy);
601+
double nextx, nexty;
602+
603+
x1 = (mode == CoordModeOrigin) ? points[i].x : x0 + points[i].x;
604+
y1 = (mode == CoordModeOrigin) ? points[i].y : y0 + points[i].y;
605+
nextx = macWin->xOff + x1 + o;
606+
nexty = macWin->yOff + y1 + o;
607+
608+
if (i == npoints-1) {
609+
if (y1 == y0) { /* horiz. line */
610+
if (x0 <= x1) {
611+
nextx = macWin->xOff + x1 + 1;
612+
} else {
613+
nextx = macWin->xOff + x1;
614+
}
615+
} else if (x1 == x0) { /* vert. line */
616+
if (y0 <= y1) {
617+
nexty = macWin->yOff + y1 + 1;
618+
} else {
619+
nexty = macWin->yOff + y1;
620+
}
621+
}
539622
}
623+
CGContextAddLineToPoint(dc.context, nextx, nexty);
624+
x0 = x1; y0 = y1;
540625
}
626+
541627
(gc->fill_rule == EvenOddRule)
542628
? CGContextEOFillPath(dc.context)
543629
: CGContextFillPath(dc.context);

0 commit comments

Comments
 (0)