From 1c4b8efb82bd0e35c91d98f2759217702f3a7c65 Mon Sep 17 00:00:00 2001 From: Ben Simms Date: Mon, 14 Oct 2024 19:32:53 +0100 Subject: [PATCH] Use masked coregraphics images on cocoa NS --- src/nsimage.m | 31 +++++++++++++++++++++++++++++++ src/nsterm.h | 8 ++++++++ src/nsterm.m | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/nsimage.m b/src/nsimage.m index ee72d6e0ea1..e36cbe5dc87 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -35,6 +35,9 @@ Updated by Christian Limpach (chris@nice.ch) #include "frame.h" #include "coding.h" +#ifdef NS_IMPL_COCOA +#include +#endif #if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MAX_ALLOWED < 1070 # define COLORSPACE_NAME NSCalibratedRGBColorSpace @@ -289,7 +292,11 @@ + (instancetype)allocInitFromFile: (Lisp_Object)file - (void)dealloc { +#ifdef NS_IMPL_COCOA + CGImageRelease(stippleMask); +#else [stippleMask release]; +#endif [bmRep release]; [transform release]; [super dealloc]; @@ -300,7 +307,11 @@ - (id)copyWithZone:(NSZone *)zone { EmacsImage *copy = [super copyWithZone:zone]; +#ifdef NS_IMPL_COCOA + copy->stippleMask = CGImageCreateCopy(stippleMask); +#else copy->stippleMask = [stippleMask copyWithZone:zone]; +#endif /* NS_IMPL_COCOA */ copy->bmRep = [bmRep copyWithZone:zone]; copy->transform = [transform copyWithZone:zone]; @@ -509,6 +520,25 @@ - (void) setAlphaAtX: (int) x Y: (int) y to: (unsigned char) a } } +#ifdef NS_IMPL_COCOA +/* Returns a cached CGImageMask of the stipple pattern */ +- (CGImageRef)stippleMask +{ + if (stippleMask == nil) { + CGDataProviderRef provider = CGDataProviderCreateWithData (NULL, [bmRep bitmapData], + [self sizeInBytes], NULL); + CGImageRef mask = CGImageMaskCreate( + [self size].width, + [self size].height, + 8, 8, [self size].width, + provider, NULL, 0); + + CGDataProviderRelease(provider); + stippleMask = CGImageRetain(mask); + } + return stippleMask; +} +#else /* Returns a pattern color, which is cached here. */ - (NSColor *)stippleMask { @@ -516,6 +546,7 @@ - (NSColor *)stippleMask stippleMask = [[NSColor colorWithPatternImage: self] retain]; return stippleMask; } +#endif /* NS_IMPL_COCOA */ /* Find the first NSBitmapImageRep which has multiple frames. */ - (NSBitmapImageRep *)getAnimatedBitmapImageRep diff --git a/src/nsterm.h b/src/nsterm.h index 6c67653705e..2370f6ea3fb 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -671,7 +671,11 @@ #define NSTRACE_UNSILENCE() { NSBitmapImageRep *bmRep; /* used for accessing pixel data */ unsigned char *pixmapData[5]; /* shortcut to access pixel data */ +#ifdef NS_IMPL_COCOA + CGImageRef stippleMask; +#else NSColor *stippleMask; +#endif // NS_IMPL_COCOA @public NSAffineTransform *transform; BOOL smoothing; @@ -688,7 +692,11 @@ #define NSTRACE_UNSILENCE() green: (unsigned char)g blue: (unsigned char)b alpha:(unsigned char)a; - (void)setAlphaAtX: (int)x Y: (int)y to: (unsigned char)a; +#ifdef NS_IMPL_COCOA +- (CGImageRef)stippleMask; +#else - (NSColor *)stippleMask; +#endif // NS_IMPL_COCOA - (Lisp_Object)getMetadata; - (BOOL)setFrame: (unsigned int) index; - (void)setTransform: (double[3][3]) m; diff --git a/src/nsterm.m b/src/nsterm.m index f68a22d9fbc..a617669cb4d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3823,8 +3823,31 @@ Function modeled after x_draw_glyph_string_box (). if (s->stippled_p) { struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f); +#ifdef NS_IMPL_COCOA + [[NSColor colorWithUnsignedLong:face->background] set]; + r = NSMakeRect (s->x, s->y + box_line_width, + s->background_width, + s->height - 2 * box_line_width); + NSRectFill (r); + s->background_filled_p = 1; + CGImageRef mask = [dpyinfo->bitmaps[face->stipple - 1].img stippleMask]; + CGRect bounds = CGRectMake (s->x, s->y + box_line_width, + s->background_width, + s->height - 2 * box_line_width); + NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; + [ctx saveGraphicsState]; + CGContextRef context = [ctx CGContext]; + CGContextClipToRect (context, bounds); + CGContextScaleCTM (context, 1, -1); + [[NSColor colorWithUnsignedLong:face->foreground] set]; + CGRect imageSize = CGRectMake (0, 0, CGImageGetWidth (mask), CGImageGetHeight (mask)); + CGContextDrawTiledImage (context, imageSize, mask); + [[NSGraphicsContext currentContext] restoreGraphicsState]; +#else [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set]; goto fill; +#endif /* NS_IMPL_COCOA */ + } else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font @@ -3847,7 +3870,9 @@ Function modeled after x_draw_glyph_string_box (). else [FRAME_CURSOR_COLOR (s->f) set]; +#ifndef NS_IMPL_COCOA fill: +#endif /* !NS_IMPL_COCOA */ r = NSMakeRect (s->x, s->y + box_line_width, s->background_width, s->height - 2 * box_line_width); @@ -4171,8 +4196,26 @@ Function modeled after x_draw_glyph_string_box (). dpyinfo = FRAME_DISPLAY_INFO (s->f); if (s->hl == DRAW_CURSOR) [FRAME_CURSOR_COLOR (s->f) set]; - else if (s->stippled_p) - [[dpyinfo->bitmaps[s->face->stipple - 1].img stippleMask] set]; + else if (s->stippled_p) { +#ifdef NS_IMPL_COCOA + [[NSColor colorWithUnsignedLong:s->face->background] set]; + NSRectFill (NSMakeRect (x, s->y, background_width, s->height)); + CGImageRef mask = [dpyinfo->bitmaps[s->face->stipple - 1].img stippleMask]; + CGRect bounds = CGRectMake (s->x, s->y, s->background_width, s->height); + NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; + [ctx saveGraphicsState]; + CGContextRef context = [ctx CGContext]; + CGContextClipToRect(context, bounds); + CGContextScaleCTM (context, 1, -1); + [[NSColor colorWithUnsignedLong:s->face->foreground] set]; + CGRect imageSize = CGRectMake (0, 0, CGImageGetWidth (mask), + CGImageGetHeight (mask)); + CGContextDrawTiledImage (context, imageSize, mask); + [[NSGraphicsContext currentContext] restoreGraphicsState]; +#else + [[dpyinfo->bitmaps[s->face->stipple - 1].img stippleMask] set]; +#endif /* NS_IMPL_COCOA */ + } else [[NSColor colorWithUnsignedLong: s->face->background] set]; -- 2.46.0