Render fringe bitmaps correctly on NextStep (bug#21301).

The fringe bitmaps were inverted, the background was not transparent,
the image data was horizontally mirrored, and periodic fringe bitmaps
were not supported.

* nsimage.m ([EmacsImage initFromXBM:width:height:fg:bg:]): When
both background and foreground colors are 0, set the background
alpha channel to 0 (making the background transparent).  When
copying the image data, do this from the most significant bit
(leftmost) to the least (rightmost), to avoid mirroring.
* nsterm.m (ns_draw_fringe_bitmap): Don't invert the image bits. Add
support for periodic images (e.g. the empty line indicator).
This commit is contained in:
Anders Lindgren 2015-11-04 06:50:19 +01:00
parent 335cb1ee15
commit 411b516d65
2 changed files with 49 additions and 11 deletions

View file

@ -202,10 +202,13 @@ - (void)dealloc
}
/* Create image from monochrome bitmap. If both FG and BG are 0
(black), set the background to white and make it transparent. */
- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
fg: (unsigned long)fg bg: (unsigned long)bg
{
unsigned char *planes[5];
unsigned char bg_alpha = 0xff;
[self initWithSize: NSMakeSize (w, h)];
@ -219,7 +222,10 @@ - (void)dealloc
[bmRep getBitmapDataPlanes: planes];
if (fg == 0 && bg == 0)
bg = 0xffffff;
{
bg = 0xffffff;
bg_alpha = 0;
}
{
/* pull bits out to set the (bytewise) alpha mask */
@ -244,21 +250,22 @@ - (void)dealloc
c = *s++;
for (k = 0; i < w && k < 8; ++k, ++i)
{
*alpha++ = 0xff;
if (c & 1)
if (c & 0x80)
{
*rr++ = fgr;
*gg++ = fgg;
*bb++ = fgb;
*alpha++ = 0xff;
}
else
{
*rr++ = bgr;
*gg++ = bgg;
*bb++ = bgb;
*alpha++ = bg_alpha;
}
idx++;
c >>= 1;
c <<= 1;
}
}
}

View file

@ -2456,11 +2456,31 @@ static NSRect constrain_frame_rect(NSRect frameRect)
External (RIF); fringe-related
-------------------------------------------------------------------------- */
{
/* Fringe bitmaps comes in two variants, normal and periodic. A
periodic bitmap is used to create a continuous pattern. Since a
bitmap is rendered one text line at a time, the start offset (dh)
of the bitmap varies. Concretely, this is used for the empty
line indicator.
For a bitmap, "h + dh" is the full height and is always
invariant. For a normal bitmap "dh" is zero.
For example, when the period is three and the full height is 72
the following combinations exists:
h=72 dh=0
h=71 dh=1
h=70 dh=2 */
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct face *face = p->face;
static EmacsImage **bimgs = NULL;
static int nBimgs = 0;
NSTRACE ("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)
{
@ -2493,19 +2513,24 @@ static NSRect constrain_frame_rect(NSRect frameRect)
if (!img)
{
unsigned short *bits = p->bits + p->dh;
int len = p->h;
// 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 (len);
unsigned char *cbits = xmalloc (full_height);
for (i = 0; i < len; i++)
cbits[i] = ~(bits[i] & 0xff);
img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
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];
bimgs[p->which - 1] = img;
xfree (cbits);
}
NSTRACE_RECT ("r", r);
NSRectClip (r);
/* Since we composite the bitmap instead of just blitting it, we need
to erase the whole background. */
@ -2523,9 +2548,15 @@ static NSRect constrain_frame_rect(NSRect frameRect)
[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);
NSTRACE_RECT ("fromRect", fromRect);
#ifdef NS_IMPL_COCOA
[img drawInRect: r
fromRect: NSZeroRect
fromRect: fromRect
operation: NSCompositeSourceOver
fraction: 1.0
respectFlipped: YES