From 1c4b8efb82bd0e35c91d98f2759217702f3a7c65 Mon Sep 17 00:00:00 2001
From: Ben Simms <ben@bensimms.moe>
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 <CoreGraphics/CoreGraphics.h>
+#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