>From 95160c34b4f41e867761f29239db02e8e7232bbe Mon Sep 17 00:00:00 2001 From: Alan Third Date: Mon, 29 Oct 2018 15:37:35 +0000 Subject: [PATCH] Fix more drawing bugs in NS port (bug#32932) * src/nsterm.m (ns_row_rect): New function. (ns_clip_to_row): Remove function. (ns_copy_bits): Fix mistake. (ns_draw_fringe_bitmap): Stop using ns_clip_to_row. (ns_draw_window_cursor): Stop using ns_clip_to_row and move ns_reset_clipping to try and force cursor drawing to be atomic. --- src/nsterm.m | 105 +++++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index 4b5d025ee3..39a7b25f60 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -796,6 +796,27 @@ Free a pool and temporary objects it refers to (callable from C) } +static NSRect +ns_row_rect (struct window *w, struct glyph_row *row, + enum glyph_row_area area) +/* Get the row as an NSRect. */ +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + NSRect rect; + int window_x, window_y, window_width; + + window_box (w, area, &window_x, &window_y, &window_width, 0); + + rect.origin.x = window_x; + rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); + rect.origin.y = max (rect.origin.y, window_y); + rect.size.width = window_width; + rect.size.height = row->visible_height; + + return rect; +} + + /* ========================================================================== Focus (clipping) and screen update @@ -1206,28 +1227,6 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) } -static BOOL -ns_clip_to_row (struct window *w, struct glyph_row *row, - enum glyph_row_area area, BOOL gc) -/* -------------------------------------------------------------------------- - Internal (but parallels other terms): Focus drawing on given row - -------------------------------------------------------------------------- */ -{ - struct frame *f = XFRAME (WINDOW_FRAME (w)); - NSRect clip_rect; - int window_x, window_y, window_width; - - window_box (w, area, &window_x, &window_y, &window_width, 0); - - clip_rect.origin.x = window_x; - clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); - clip_rect.origin.y = max (clip_rect.origin.y, window_y); - clip_rect.size.width = window_width; - clip_rect.size.height = row->visible_height; - - return ns_clip_to_rect (f, &clip_rect, 1); -} - /* ========================================================================== Visible bell and beep. @@ -2692,7 +2691,7 @@ so some key presses (TAB) are swallowed by the system. */ ns_copy_bits (struct frame *f, NSRect src, NSRect dest) { NSSize delta = NSMakeSize (dest.origin.x - src.origin.x, - dest.origin.y - src.origin.y) + dest.origin.y - src.origin.y); NSTRACE ("ns_copy_bits"); if (FRAME_NS_VIEW (f)) @@ -2911,6 +2910,9 @@ so some key presses (TAB) are swallowed by the system. */ struct face *face = p->face; static EmacsImage **bimgs = NULL; static int nBimgs = 0; + NSRect clearRect = NSZeroRect; + NSRect imageRect = NSZeroRect; + NSRect rowRect = ns_row_rect (w, row, ANY_AREA); NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap"); NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", @@ -2925,25 +2927,40 @@ so some key presses (TAB) are swallowed by the system. */ nBimgs = max_used_fringe_bitmap; } - /* Must clip because of partially visible lines. */ - if (ns_clip_to_row (w, row, ANY_AREA, YES)) + /* Work out the rectangle we will composite into. */ + if (p->which) + imageRect = NSMakeRect (p->x, p->y, p->wd, p->h); + + /* Work out the rectangle we will need to clear. Because we're + compositing rather than blitting, we need to clear the area under + the image regardless of anything else. */ + if (!p->overlay_p) + { + clearRect = NSMakeRect (p->bx, p->by, p->nx, p->ny); + clearRect = NSUnionRect (clearRect, imageRect); + } + else { - if (!p->overlay_p) + clearRect = imageRect; + } + + /* Handle partially visible rows. */ + clearRect = NSIntersectionRect (clearRect, rowRect); + + /* The visible portion of imageRect will always be contained within + clearRect. */ + if (ns_clip_to_rect (f, &clearRect, 1)) + { + if (! NSIsEmptyRect (clearRect)) { - int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; + NSTRACE_RECT ("clearRect", clearRect); - if (bx >= 0 && nx > 0) - { - NSRect r = NSMakeRect (bx, by, nx, ny); - NSRectClip (r); - [ns_lookup_indexed_color (face->background, f) set]; - NSRectFill (r); - } + [ns_lookup_indexed_color(face->background, f) set]; + NSRectFill (clearRect); } if (p->which) { - NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); EmacsImage *img = bimgs[p->which - 1]; if (!img) @@ -2964,13 +2981,6 @@ so some key presses (TAB) are swallowed by the system. */ xfree (cbits); } - NSTRACE_RECT ("r", r); - - NSRectClip (r); - /* Since we composite the bitmap instead of just blitting it, we need - to erase the whole background. */ - [ns_lookup_indexed_color(face->background, f) set]; - NSRectFill (r); { NSColor *bm_color; @@ -2990,7 +3000,7 @@ so some key presses (TAB) are swallowed by the system. */ NSTRACE_RECT ("fromRect", fromRect); - [img drawInRect: r + [img drawInRect: imageRect fromRect: fromRect operation: NSCompositingOperationSourceOver fraction: 1.0 @@ -2998,7 +3008,7 @@ so some key presses (TAB) are swallowed by the system. */ hints: nil]; #else { - NSPoint pt = r.origin; + NSPoint pt = imageRect.origin; pt.y += p->h; [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; } @@ -3088,7 +3098,9 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. r.size.width = w->phys_cursor_width; /* Prevent the cursor from being drawn outside the text area. */ - if (ns_clip_to_row (w, glyph_row, TEXT_AREA, NO)) + r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA)); + + if (ns_clip_to_rect (f, &r, 1)) { face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); if (face && NS_FACE_BACKGROUND (face) @@ -3128,11 +3140,12 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. NSRectFill (s); break; } - ns_reset_clipping (f); /* draw the character under the cursor */ if (cursor_type != NO_CURSOR) draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); + + ns_reset_clipping (f); } } -- 2.18.0