]> git.eshelyaron.com Git - emacs.git/commitdiff
Convert fringe bitmaps to vectors on NS port
authorAlan Third <alan@idiocy.org>
Sat, 24 Jul 2021 15:08:09 +0000 (16:08 +0100)
committerAlan Third <alan@idiocy.org>
Mon, 26 Jul 2021 22:12:31 +0000 (23:12 +0100)
Unfortunately *step doesn't support masks for bitmap images so
changing the colors of fringe bitmaps is awkward.  We can work around
this by converting the bitmap into an NSBezierPath and drawing it in
the required color.

* src/nsterm.m (ns_define_fringe_bitmap):
(ns_destroy_fringe_bitmap): New functions
(ns_draw_fringe_bitmap): Display the NSBezierPath.
* src/nsimage.m
([EmacsImage initFromXBM:width:height:fg:bg:reverseBytes:]): Remove
variable that's there to allow us to easily modify the XBM colors.
([EmacsImage setXBMColor:]): Remove method.

src/nsimage.m
src/nsterm.h
src/nsterm.m

index 3668a7ab1077af7ada86dba83d90cb13b7cb74ce..dd2bb3b0d7bcf2f3e0f030bf5cf75ffefe2eb7f2 100644 (file)
@@ -377,51 +377,10 @@ ns_image_size_in_bytes (void *img)
         }
   }
 
-  xbm_fg = fg;
   [self addRepresentation: bmRep];
   return self;
 }
 
-/* Set color for a bitmap image.  */
-- (instancetype)setXBMColor: (NSColor *)color
-{
-  NSSize s = [self size];
-  unsigned char *planes[5];
-  EmacsCGFloat r, g, b, a;
-  NSColor *rgbColor;
-
-  if (bmRep == nil || color == nil)
-    return self;
-
-  if ([color colorSpace] != [NSColorSpace genericRGBColorSpace])
-    rgbColor = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
-  else
-    rgbColor = color;
-
-  [rgbColor getRed: &r green: &g blue: &b alpha: &a];
-
-  [bmRep getBitmapDataPlanes: planes];
-
-  {
-    int i, len = s.width*s.height;
-    int rr = r * 0xff, gg = g * 0xff, bb = b * 0xff;
-    unsigned char fgr = (xbm_fg >> 16) & 0xff;
-    unsigned char fgg = (xbm_fg >> 8) & 0xff;
-    unsigned char fgb = xbm_fg & 0xff;
-
-    for (i = 0; i < len; ++i)
-      if (planes[0][i] == fgr && planes[1][i] == fgg && planes[2][i] == fgb)
-        {
-          planes[0][i] = rr;
-          planes[1][i] = gg;
-          planes[2][i] = bb;
-        }
-    xbm_fg = ((rr << 16) & 0xff0000) + ((gg << 8) & 0xff00) + (bb & 0xff);
-  }
-
-  return self;
-}
-
 
 - (instancetype)initForXPMWithDepth: (int)depth width: (int)width height: (int)height
 {
index b29e76cc63f07df2ce0c186ef20ced3f90a1d32b..57c1e4cbae0ca6b5dc5b9d4d238f65918f2e3fc5 100644 (file)
@@ -647,7 +647,6 @@ typedef id instancetype;
   NSBitmapImageRep *bmRep; /* used for accessing pixel data */
   unsigned char *pixmapData[5]; /* shortcut to access pixel data */
   NSColor *stippleMask;
-  unsigned long xbm_fg;
 @public
   NSAffineTransform *transform;
   BOOL smoothing;
@@ -657,7 +656,6 @@ typedef id instancetype;
 - (instancetype)initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
                          fg: (unsigned long)fg bg: (unsigned long)bg
                reverseBytes: (BOOL)reverse;
-- (instancetype)setXBMColor: (NSColor *)color;
 - (instancetype)initForXPMWithDepth: (int)depth width: (int)width height: (int)height;
 - (void)setPixmapData;
 - (unsigned long)getPixelAtX: (int)x Y: (int)y;
index 9eff01c7246266626329a2f7877c2c82a2adeadd..853c0fa2fa951a64bed78e9643ed826865fd8a14 100644 (file)
@@ -3067,6 +3067,39 @@ ns_compute_glyph_string_overhangs (struct glyph_string *s)
 
    ========================================================================== */
 
+static NSMutableDictionary *fringe_bmp;
+
+static void
+ns_define_fringe_bitmap (int which, unsigned short *bits, int h, int w)
+{
+  NSBezierPath *p = [NSBezierPath bezierPath];
+
+  if (!fringe_bmp)
+    fringe_bmp = [[NSMutableDictionary alloc] initWithCapacity:25];
+
+  [p moveToPoint:NSMakePoint (0, 0)];
+
+  for (int y = 0 ; y < h ; y++)
+    for (int x = 0 ; x < w ; x++)
+      {
+        /* XBM rows are always round numbers of bytes, with any unused
+           bits ignored.  */
+        int byte = y * (w/8 + (w%8 ? 1 : 0)) + x/8;
+        bool bit = bits[byte] & (0x80 >> x%8);
+        if (bit)
+          [p appendBezierPathWithRect:NSMakeRect (x, y, 1, 1)];
+      }
+
+  [fringe_bmp setObject:p forKey:[NSNumber numberWithInt:which]];
+}
+
+
+static void
+ns_destroy_fringe_bitmap (int which)
+{
+  [fringe_bmp removeObjectForKey:[NSNumber numberWithInt:which]];
+}
+
 
 extern int max_used_fringe_bitmap;
 static void
@@ -3094,41 +3127,18 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
 
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   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",
                p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh);
 
-  /* grow bimgs if needed */
-  if (nBimgs < max_used_fringe_bitmap)
-    {
-      bimgs = xrealloc (bimgs, max_used_fringe_bitmap * sizeof *bimgs);
-      memset (bimgs + nBimgs, 0,
-             (max_used_fringe_bitmap - nBimgs) * sizeof *bimgs);
-      nBimgs = max_used_fringe_bitmap;
-    }
-
-  /* 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.  */
+  clearRect = 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->bx >= 0 && !p->overlay_p)
-    {
-      clearRect = NSMakeRect (p->bx, p->by, p->nx, p->ny);
-      clearRect = NSUnionRect (clearRect, imageRect);
-    }
-  else
-    {
-      clearRect = imageRect;
-    }
+    clearRect = NSUnionRect (clearRect, NSMakeRect (p->bx, p->by, p->nx, p->ny));
 
   /* Handle partially visible rows.  */
   clearRect = NSIntersectionRect (clearRect, rowRect);
@@ -3144,53 +3154,29 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
       NSRectFill (clearRect);
     }
 
-  if (p->which)
+  NSBezierPath *bmp = [fringe_bmp objectForKey:[NSNumber numberWithInt:p->which]];
+  if (bmp)
     {
-      EmacsImage *img = bimgs[p->which - 1];
-
-      if (!img)
-        {
-          // Note: For "periodic" images, allocate one EmacsImage for
-          // the base image, and use it for all dh:s.
-          unsigned short *bits = p->bits;
-          int full_height = p->h + p->dh;
-          int i;
-          unsigned char *cbits = xmalloc (full_height);
-
-          for (i = 0; i < full_height; i++)
-            cbits[i] = bits[i];
-          img = [[EmacsImage alloc] initFromXBM: cbits width: 8
-                                         height: full_height
-                                             fg: 0 bg: 0
-                                   reverseBytes: NO];
-          bimgs[p->which - 1] = img;
-          xfree (cbits);
-        }
+      NSAffineTransform *transform = [NSAffineTransform transform];
+      NSColor *bm_color;
 
+      /* Because the image is defined at (0, 0) we need to take a copy
+         and then transform that copy to the new origin.  */
+      bmp = [bmp copy];
+      [transform translateXBy:p->x yBy:p->y - p->dh];
+      [bmp transformUsingAffineTransform:transform];
 
-      {
-        NSColor *bm_color;
-        if (!p->cursor_p)
-          bm_color = ns_lookup_indexed_color(face->foreground, f);
-        else if (p->overlay_p)
-          bm_color = ns_lookup_indexed_color(face->background, f);
-        else
-          bm_color = f->output_data.ns->cursor_color;
-        [img setXBMColor: bm_color];
-      }
-
-      // Note: For periodic images, the full image height is "h + hd".
-      // By using the height h, a suitable part of the image is used.
-      NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
+      if (!p->cursor_p)
+        bm_color = ns_lookup_indexed_color(face->foreground, f);
+      else if (p->overlay_p)
+        bm_color = ns_lookup_indexed_color(face->background, f);
+      else
+        bm_color = f->output_data.ns->cursor_color;
 
-      NSTRACE_RECT ("fromRect", fromRect);
+      [bm_color set];
+      [bmp fill];
 
-      [img drawInRect: imageRect
-             fromRect: fromRect
-            operation: NSCompositingOperationSourceOver
-             fraction: 1.0
-           respectFlipped: YES
-                hints: nil];
+      [bmp release];
     }
   ns_unfocus (f);
 }
@@ -5162,8 +5148,8 @@ static struct redisplay_interface ns_redisplay_interface =
   gui_get_glyph_overhangs,
   gui_fix_overlapping_area,
   ns_draw_fringe_bitmap,
-  0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
-  0, /* destroy_fringe_bitmap */
+  ns_define_fringe_bitmap,
+  ns_destroy_fringe_bitmap,
   ns_compute_glyph_string_overhangs,
   ns_draw_glyph_string,
   ns_define_frame_cursor,
@@ -5349,6 +5335,8 @@ ns_term_init (Lisp_Object display_name)
 
   terminal->name = xlispstrdup (display_name);
 
+  gui_init_fringe (terminal->rif);
+
   unblock_input ();
 
   if (!inhibit_x_resources)