Metal: clip glyph strings with the engine clip rect (scissor)
The NS backend clips every glyph string draw to get_glyph_string_clip_rect via ns_focus; Metal drew unclipped. The most visible casualty: a filled-box cursor on a tall row (e.g. a line with an inline image) painted the cursor background over the full row height (60px bar) instead of the character cell, because draw_phys_cursor_glyph relies on the clip rect, narrowed to the physical cursor box, to bound the DRAW_CURSOR background fill. Apply the same rect as an MTLScissorRect around each glyph string draw (applyClipRect:/clearClipRect on the static-texture encoder, mapped to physical pixels and clamped), in both the in-cycle and immediate paths. Also bounds overhang bleed into neighboring windows for free. Verified: cursor on an image row now renders as a character-sized box with the glyph inverted, identical to NS; baseline AE unchanged (0.068%).
This commit is contained in:
parent
bb374d3a0c
commit
35d20a24e8
1 changed files with 47 additions and 0 deletions
|
|
@ -1044,10 +1044,47 @@ easing_apply (MtlScrollEasing mode, float t)
|
|||
- (void)shiftGlyphsX:(int)x y:(int)y width:(int)w height:(int)h by:(int)shift;
|
||||
- (void)drawFringeBits:(unsigned short *)bits dh:(int)dh wd:(int)wd h:(int)h
|
||||
atX:(int)x y:(int)y color:(unsigned long)color;
|
||||
- (void)applyClipRect:(NSRect)r;
|
||||
- (void)clearClipRect;
|
||||
@end
|
||||
|
||||
@implementation MtlFrameData
|
||||
|
||||
/* Clip subsequent draws on the current encoder to R (logical pixels), like the
|
||||
NS backend's ns_focus clipping with get_glyph_string_clip_rect. This is what
|
||||
keeps a filled-box cursor on a tall row (e.g. an image line) at the size of
|
||||
the character cell instead of the whole row, and stops overhangs from
|
||||
bleeding outside the window area. */
|
||||
- (void)applyClipRect:(NSRect)r
|
||||
{
|
||||
if (!self.encoder || !self.staticTexture) return;
|
||||
CGSize dsz = self.metalLayer.drawableSize;
|
||||
NSSize lsz = self.metalLayer.frame.size;
|
||||
double scx = lsz.width > 0 ? dsz.width / lsz.width : 1.0;
|
||||
double scy = lsz.height > 0 ? dsz.height / lsz.height : 1.0;
|
||||
long tw = (long) self.staticTexture.width;
|
||||
long th = (long) self.staticTexture.height;
|
||||
long x0 = lround (NSMinX (r) * scx), y0 = lround (NSMinY (r) * scy);
|
||||
long x1 = lround (NSMaxX (r) * scx), y1 = lround (NSMaxY (r) * scy);
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (y0 < 0) y0 = 0;
|
||||
if (x1 > tw) x1 = tw;
|
||||
if (y1 > th) y1 = th;
|
||||
if (x1 <= x0 || y1 <= y0)
|
||||
{ x0 = tw - 1; y0 = th - 1; x1 = tw; y1 = th; } /* effectively clip out */
|
||||
MTLScissorRect sc = { (NSUInteger) x0, (NSUInteger) y0,
|
||||
(NSUInteger) (x1 - x0), (NSUInteger) (y1 - y0) };
|
||||
[self.encoder setScissorRect:sc];
|
||||
}
|
||||
|
||||
- (void)clearClipRect
|
||||
{
|
||||
if (!self.encoder || !self.staticTexture) return;
|
||||
MTLScissorRect sc = { 0, 0, self.staticTexture.width,
|
||||
self.staticTexture.height };
|
||||
[self.encoder setScissorRect:sc];
|
||||
}
|
||||
|
||||
/* Open a render command encoder targeting the static texture. CLEAR wipes it to
|
||||
the frame background (only for a fresh/resized texture); otherwise LOAD
|
||||
preserves the previous content (Emacs redraws just the dirty regions).
|
||||
|
|
@ -2481,14 +2518,24 @@ mtl_draw_glyph_string (struct glyph_string *s)
|
|||
state leak into the next click/redisplay. Committing per draw keeps the
|
||||
pipeline clean, and deferring the present lets mtl_flush_display show the
|
||||
whole sequence in one composite. */
|
||||
/* Clip to the same rect the NS backend uses (window area; narrowed to the
|
||||
physical cursor box for DRAW_CURSOR strings, which is what keeps the
|
||||
filled-box cursor character-sized on tall image rows). */
|
||||
NSRect clip;
|
||||
get_glyph_string_clip_rect (s, &clip);
|
||||
|
||||
if (fd.encoder)
|
||||
{
|
||||
[fd applyClipRect:clip];
|
||||
mtl_draw_glyph_string_impl (s);
|
||||
[fd clearClipRect];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fd beginFrame];
|
||||
[fd applyClipRect:clip];
|
||||
mtl_draw_glyph_string_impl (s);
|
||||
[fd clearClipRect];
|
||||
[fd endFramePresent:NO];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue