aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBen Simms2025-01-05 20:03:53 +0100
committerEli Zaretskii2025-03-04 14:31:35 +0200
commit9cbbdcee132588a11dc03c3da371176aaa13927c (patch)
treea6051b5234fe0bcb9256d8d7aef17ecc52abb002 /src
parentfe7a8c92be6269f8fc7933eb6c190178839d0f8a (diff)
downloademacs-9cbbdcee132588a11dc03c3da371176aaa13927c.tar.gz
emacs-9cbbdcee132588a11dc03c3da371176aaa13927c.zip
Support colored stipples on Cocoa NS (Bug#73384)
On Cocoa builds of NS Emacs, stipples are now rendered using masked CGImages instead of patterned NSColors so that stipples now render with color. * src/nsimage.m ([EmacsImage stippleMask:]): Use a CGImageMask to store the stipple mask when building for Cocoa. * src/nsterm.m (ns_maybe_dumpglyphs_background): Perform a masked fill to draw stipples when building for Cocoa. (ns_draw_stretch_glyph_string): Perform a masked fill to draw stipples when building for Cocoa.
Diffstat (limited to 'src')
-rw-r--r--src/nsimage.m31
-rw-r--r--src/nsterm.h8
-rw-r--r--src/nsterm.m68
3 files changed, 106 insertions, 1 deletions
diff --git a/src/nsimage.m b/src/nsimage.m
index e8c82269bce..8f1653d085a 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -35,6 +35,9 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
35#include "frame.h" 35#include "frame.h"
36#include "coding.h" 36#include "coding.h"
37 37
38#ifdef NS_IMPL_COCOA
39#include <CoreGraphics/CoreGraphics.h>
40#endif
38 41
39#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MAX_ALLOWED < 1070 42#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MAX_ALLOWED < 1070
40# define COLORSPACE_NAME NSCalibratedRGBColorSpace 43# define COLORSPACE_NAME NSCalibratedRGBColorSpace
@@ -289,7 +292,11 @@ ns_image_size_in_bytes (void *img)
289 292
290- (void)dealloc 293- (void)dealloc
291{ 294{
295#ifdef NS_IMPL_COCOA
296 CGImageRelease(stippleMask);
297#else
292 [stippleMask release]; 298 [stippleMask release];
299#endif
293 [bmRep release]; 300 [bmRep release];
294 [transform release]; 301 [transform release];
295 [super dealloc]; 302 [super dealloc];
@@ -300,7 +307,11 @@ ns_image_size_in_bytes (void *img)
300{ 307{
301 EmacsImage *copy = [super copyWithZone:zone]; 308 EmacsImage *copy = [super copyWithZone:zone];
302 309
310#ifdef NS_IMPL_COCOA
311 copy->stippleMask = CGImageCreateCopy(stippleMask);
312#else
303 copy->stippleMask = [stippleMask copyWithZone:zone]; 313 copy->stippleMask = [stippleMask copyWithZone:zone];
314#endif /* NS_IMPL_COCOA */
304 copy->bmRep = [bmRep copyWithZone:zone]; 315 copy->bmRep = [bmRep copyWithZone:zone];
305 copy->transform = [transform copyWithZone:zone]; 316 copy->transform = [transform copyWithZone:zone];
306 317
@@ -509,6 +520,25 @@ ns_image_size_in_bytes (void *img)
509 } 520 }
510} 521}
511 522
523#ifdef NS_IMPL_COCOA
524/* Returns a cached CGImageMask of the stipple pattern */
525- (CGImageRef)stippleMask
526{
527 if (stippleMask == nil)
528 {
529 CGDataProviderRef provider = CGDataProviderCreateWithData (NULL, [bmRep bitmapData],
530 [self sizeInBytes], NULL);
531 CGImageRef mask = CGImageMaskCreate([self size].width,
532 [self size].height,
533 8, 8, [self size].width,
534 provider, NULL, 0);
535
536 CGDataProviderRelease(provider);
537 stippleMask = CGImageRetain(mask);
538 }
539 return stippleMask;
540}
541#else
512/* Returns a pattern color, which is cached here. */ 542/* Returns a pattern color, which is cached here. */
513- (NSColor *)stippleMask 543- (NSColor *)stippleMask
514{ 544{
@@ -516,6 +546,7 @@ ns_image_size_in_bytes (void *img)
516 stippleMask = [[NSColor colorWithPatternImage: self] retain]; 546 stippleMask = [[NSColor colorWithPatternImage: self] retain];
517 return stippleMask; 547 return stippleMask;
518} 548}
549#endif /* NS_IMPL_COCOA */
519 550
520/* Find the first NSBitmapImageRep which has multiple frames. */ 551/* Find the first NSBitmapImageRep which has multiple frames. */
521- (NSBitmapImageRep *)getAnimatedBitmapImageRep 552- (NSBitmapImageRep *)getAnimatedBitmapImageRep
diff --git a/src/nsterm.h b/src/nsterm.h
index d03908eb521..0009f1ab2bf 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -671,7 +671,11 @@ enum ns_return_frame_mode
671{ 671{
672 NSBitmapImageRep *bmRep; /* used for accessing pixel data */ 672 NSBitmapImageRep *bmRep; /* used for accessing pixel data */
673 unsigned char *pixmapData[5]; /* shortcut to access pixel data */ 673 unsigned char *pixmapData[5]; /* shortcut to access pixel data */
674#ifdef NS_IMPL_COCOA
675 CGImageRef stippleMask;
676#else
674 NSColor *stippleMask; 677 NSColor *stippleMask;
678#endif /* NS_IMPL_COCOA */
675@public 679@public
676 NSAffineTransform *transform; 680 NSAffineTransform *transform;
677 BOOL smoothing; 681 BOOL smoothing;
@@ -688,7 +692,11 @@ enum ns_return_frame_mode
688 green: (unsigned char)g blue: (unsigned char)b 692 green: (unsigned char)g blue: (unsigned char)b
689 alpha:(unsigned char)a; 693 alpha:(unsigned char)a;
690- (void)setAlphaAtX: (int)x Y: (int)y to: (unsigned char)a; 694- (void)setAlphaAtX: (int)x Y: (int)y to: (unsigned char)a;
695#ifdef NS_IMPL_COCOA
696- (CGImageRef)stippleMask;
697#else
691- (NSColor *)stippleMask; 698- (NSColor *)stippleMask;
699#endif /* NS_IMPL_COCOA */
692- (Lisp_Object)getMetadata; 700- (Lisp_Object)getMetadata;
693- (BOOL)setFrame: (unsigned int) index; 701- (BOOL)setFrame: (unsigned int) index;
694- (void)setTransform: (double[3][3]) m; 702- (void)setTransform: (double[3][3]) m;
diff --git a/src/nsterm.m b/src/nsterm.m
index 12141dfac44..745addfc46c 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3817,8 +3817,41 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
3817 if (s->stippled_p) 3817 if (s->stippled_p)
3818 { 3818 {
3819 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f); 3819 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
3820#ifdef NS_IMPL_COCOA
3821 /* On cocoa emacs the stipple is stored as a mask CGImage.
3822 First we want to clear the background with the bg colour */
3823 [[NSColor colorWithUnsignedLong:face->background] set];
3824 r = NSMakeRect (s->x, s->y + box_line_width,
3825 s->background_width,
3826 s->height - 2 * box_line_width);
3827 NSRectFill (r);
3828 s->background_filled_p = 1;
3829 CGImageRef mask =
3830 [dpyinfo->bitmaps[face->stipple - 1].img stippleMask];
3831
3832 /* This part could possibly be improved, the author is
3833 unfamiliar with NS/CoreGraphics and isn't sure if it's
3834 possible to do this with NSImage */
3835 NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
3836 [ctx saveGraphicsState];
3837 /* Checkpoint the graphics state and then focus in on the area
3838 we're going to fill */
3839 CGContextRef context = [ctx CGContext];
3840 CGContextClipToRect (context, r);
3841 CGContextScaleCTM (context, 1, -1);
3842
3843 /* Stamp the foreground colour using the stipple mask */
3844 [[NSColor colorWithUnsignedLong:face->foreground] set];
3845 CGRect imageSize = CGRectMake (0, 0, CGImageGetWidth (mask),
3846 CGImageGetHeight (mask));
3847 CGContextDrawTiledImage (context, imageSize, mask);
3848
3849 [[NSGraphicsContext currentContext] restoreGraphicsState];
3850#else
3820 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set]; 3851 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
3821 goto fill; 3852 goto fill;
3853#endif /* NS_IMPL_COCOA */
3854
3822 } 3855 }
3823 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 3856 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3824 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font 3857 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
@@ -3841,7 +3874,9 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
3841 else 3874 else
3842 [FRAME_CURSOR_COLOR (s->f) set]; 3875 [FRAME_CURSOR_COLOR (s->f) set];
3843 3876
3877#ifndef NS_IMPL_COCOA
3844 fill: 3878 fill:
3879#endif /* !NS_IMPL_COCOA */
3845 r = NSMakeRect (s->x, s->y + box_line_width, 3880 r = NSMakeRect (s->x, s->y + box_line_width,
3846 s->background_width, 3881 s->background_width,
3847 s->height - 2 * box_line_width); 3882 s->height - 2 * box_line_width);
@@ -4166,7 +4201,38 @@ ns_draw_stretch_glyph_string (struct glyph_string *s)
4166 if (s->hl == DRAW_CURSOR) 4201 if (s->hl == DRAW_CURSOR)
4167 [FRAME_CURSOR_COLOR (s->f) set]; 4202 [FRAME_CURSOR_COLOR (s->f) set];
4168 else if (s->stippled_p) 4203 else if (s->stippled_p)
4169 [[dpyinfo->bitmaps[s->face->stipple - 1].img stippleMask] set]; 4204 {
4205#ifdef NS_IMPL_COCOA
4206 /* On cocoa emacs the stipple is stored as a mask CGImage.
4207 First we want to clear the background with the bg
4208 colour */
4209 [[NSColor colorWithUnsignedLong:s->face->background] set];
4210 NSRectFill (NSMakeRect (x, s->y, background_width, s->height));
4211
4212 /* This part could possibly be improved, the author is
4213 unfamiliar with NS/CoreGraphics and isn't sure if it's
4214 possible to do this with NSImage */
4215 CGImageRef mask = [dpyinfo->bitmaps[s->face->stipple - 1].img stippleMask];
4216 CGRect bounds = CGRectMake (s->x, s->y, s->background_width, s->height);
4217
4218 /* Checkpoint the graphics state and then focus in on the
4219 area we're going to fill */
4220 NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
4221 [ctx saveGraphicsState];
4222 CGContextRef context = [ctx CGContext];
4223 CGContextClipToRect(context, bounds);
4224 CGContextScaleCTM (context, 1, -1);
4225
4226 /* Stamp the foreground colour using the stipple mask */
4227 [[NSColor colorWithUnsignedLong:s->face->foreground] set];
4228 CGRect imageSize = CGRectMake (0, 0, CGImageGetWidth (mask),
4229 CGImageGetHeight (mask));
4230 CGContextDrawTiledImage (context, imageSize, mask);
4231 [[NSGraphicsContext currentContext] restoreGraphicsState];
4232#else
4233 [[dpyinfo->bitmaps[s->face->stipple - 1].img stippleMask] set];
4234#endif /* NS_IMPL_COCOA */
4235 }
4170 else 4236 else
4171 [[NSColor colorWithUnsignedLong: s->face->background] set]; 4237 [[NSColor colorWithUnsignedLong: s->face->background] set];
4172 4238