Allow negative line width for :box face attribute

Separate values for box line width and height and allow both to be
negative which makes the visual width and height of the boxed string
unchanged (Bug#13011).

* doc/lispref/display.texi (Face Attributes): Modify :box attribute
description to reflect the new possibilities.
* lisp/cus-face.el (custom-face-attributes): Set box attribute to get
two integer to set vertical and horizontal width and modify pre-filter
to accept dotted list of two int as valid box attribute.
* src/dispextern.h (face): Use two int for box horizontal and vertical
line width.

* src/nsfont.m (nsfont_draw): Use new face attributes.
* src/nsterm.m (ns_draw_box, ns_draw_relief): Support separated
horizontal and vertical box line width.
(ns_dumpglyphs_box_or_relief, ns_maybe_dumpglyphs_background)
(ns_dumpglyphs_image, ns_draw_glyph_string_foreground)
(ns_draw_composite_glyph_string_foreground): Use new face attributes.

* src/w32term.c (w32_draw_box_rect, w32_draw_relief_rect): Support
separated horizontal and vertical box line width.
(x_draw_glyph_string_background, x_draw_glyph_string_foreground)
(x_draw_composite_glyph_string_foreground)
(x_draw_glyphless_glyph_string_foreground, x_draw_glyph_string_box)
(x_draw_image_foreground, x_draw_image_relief)
(w32_draw_image_foreground_1, x_draw_image_glyph_string): Use new face
attributes.

* src/xfaces.c (Sinternal_set_lisp_face_attribute, realize_x_face):
Accept box attribute as a list of two ints.

* src/xdisp.c (estimate_mode_line_height, produce_image_glyph)
(produce_xwidget_glyph, x_produce_glyphs): Use new face attributes.
* src/xterm.c (x_draw_box_rect, x_draw_relief_rect): Support separated
horizontal and vertical box line width.
(x_draw_glyph_string_background, x_draw_glyph_string_foreground)
(x_draw_composite_glyph_string_foreground)
(x_draw_glyphless_glyph_string_foreground, x_draw_glyph_string_box)
(x_draw_image_foreground, x_draw_image_relief, x_draw_image_foreground_1)
(x_draw_image_glyph_string): Use new face attributes.
This commit is contained in:
Alexandre Adolphe 2019-08-10 22:57:24 +02:00 committed by Noam Postavsky
parent b538cd88b4
commit 34ae2d0c22
9 changed files with 227 additions and 213 deletions

View file

@ -2444,12 +2444,15 @@ Draw a box with lines of width 1, in the foreground color.
@item @var{color}
Draw a box with lines of width 1, in color @var{color}.
@item @code{(:line-width @var{width} :color @var{color} :style @var{style})}
This way you can explicitly specify all aspects of the box. The value
@var{width} specifies the width of the lines to draw; it defaults to
1. A negative width @minus{}@var{n} means to draw a line of width @var{n}
whose top and bottom parts occupy the space of the underlying text,
thus avoiding any increase in the character height.
@item @code{(:line-width (@var{vwidth} . @var{hwidth}) :color @var{color} :style @var{style})}
This way you can explicitly specify all aspects of the box. The values
@var{vwidth} and @var{hwidth} specifies respectively the width of the
vertical and horizontal lines to draw; they default to (1 . 1).
A negative horizontal or vertical width @minus{}@var{n} means to draw a line
of width @var{n} that occupies the space of the underlying text, thus
avoiding any increase in the character height or width. For simplification
the width could be specified with only a single number @var{n} instead
of a list, such case is equivalent to @code{((abs @var{n}) . @var{n})}.
The value @var{color} specifies the color to draw with. The default is
the foreground color of the face for simple boxes, and the background

View file

@ -166,9 +166,11 @@
:help-echo "Control box around text."
(const :tag "Off" nil)
(list :tag "Box"
:value (:line-width 2 :color "grey75" :style released-button)
(const :format "" :value :line-width)
(integer :tag "Width")
:value (:line-width (2 . 2) :color "grey75" :style released-button)
(const :format "" :value :line-width)
(cons :tag "Width" :extra-offset 2
(integer :tag "Vertical")
(integer :tag "Horizontal"))
(const :format "" :value :color)
(choice :tag "Color" (const :tag "*" nil) color)
(const :format "" :value :style)
@ -181,15 +183,19 @@
(and real-value
(let ((lwidth
(or (and (consp real-value)
(plist-get real-value :line-width))
(if (listp (cdr real-value))
(plist-get real-value :line-width)
real-value))
(and (integerp real-value) real-value)
1))
'(1 . 1)))
(color
(or (and (consp real-value) (plist-get real-value :color))
(and (stringp real-value) real-value)
nil))
(style
(and (consp real-value) (plist-get real-value :style))))
(if (integerp lwidth)
(setq lwidth (cons (abs lwidth) lwidth)))
(list :line-width lwidth :color color :style style))))
;; filter to make customized-value suitable for storing
(lambda (cus-value)

View file

@ -1693,12 +1693,17 @@ struct face
int fontset;
/* Non-zero means characters in this face have a box of that
thickness around them. If this value is negative, its absolute
value indicates the thickness, and the horizontal (top and
bottom) borders of box are drawn inside of the character glyphs'
area. The vertical (left and right) borders of the box are drawn
in the same way as when this value is positive. */
int box_line_width;
thickness around them. Vertical (left and right) and horizontal
(top and bottom) borders size can be set separatedly using an
associated list of two ints in the form
(vertical_size . horizontal_size). In case one of the value is
negative, its absolute value indicates the thickness, and the
borders of box are drawn inside of the character glyphs' area
potentially over the glyph itself but the glyph drawing size is
not increase. If a (signed) int N is use instead of a list, it
is the same as setting ( abs(N) . N ) values. */
int box_vertical_line_width;
int box_horizontal_line_width;
/* Type of box drawn. A value of FACE_NO_BOX means no box is drawn
around text in this face. A value of FACE_SIMPLE_BOX means a box

View file

@ -1043,7 +1043,7 @@ is false when (FROM > 0 || TO < S->nchars). */
r.origin.x = s->x;
if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
r.origin.x += abs (s->face->box_line_width);
r.origin.x += max (s->face->box_vertical_line_width, 0);
r.origin.y = s->y;
r.size.height = FONT_HEIGHT (font);
@ -1105,7 +1105,7 @@ is false when (FROM > 0 || TO < S->nchars). */
{
NSRect br = r;
int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
int mbox_line_width = max (s->face->box_line_width, 0);
int mbox_line_width = max (s->face->box_vertical_line_width, 0);
if (s->row->full_width_p)
{
@ -1129,9 +1129,10 @@ is false when (FROM > 0 || TO < S->nchars). */
}
else
{
int correction = abs (s->face->box_line_width)+1;
int correction = abs (s->face->box_horizontal_line_width)+1;
br.origin.y += correction;
br.size.height -= 2*correction;
correction = abs (s->face->box_vertical_line_width)+1;
br.origin.x += correction;
br.size.width -= 2*correction;
}

View file

@ -3639,8 +3639,8 @@ larger if there are taller display elements (e.g., characters
}
static void
ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
char left_p, char right_p)
ns_draw_box (NSRect r, CGFloat hthickness, CGFloat vthickness,
NSColor *col, char left_p, char right_p)
/* --------------------------------------------------------------------------
Draw an unfilled rect inside r, optionally leaving left and/or right open.
Note we can't just use an NSDrawRect command, because of the possibility
@ -3651,28 +3651,28 @@ larger if there are taller display elements (e.g., characters
[col set];
/* top, bottom */
s.size.height = thickness;
s.size.height = hthickness;
NSRectFill (s);
s.origin.y += r.size.height - thickness;
s.origin.y += r.size.height - hthickness;
NSRectFill (s);
s.size.height = r.size.height;
s.origin.y = r.origin.y;
/* left, right (optional) */
s.size.width = thickness;
s.size.width = vthickness;
if (left_p)
NSRectFill (s);
if (right_p)
{
s.origin.x += r.size.width - thickness;
s.origin.x += r.size.width - vthickness;
NSRectFill (s);
}
}
static void
ns_draw_relief (NSRect r, int thickness, char raised_p,
ns_draw_relief (NSRect r, int hthickness, int vthickness, char raised_p,
char top_p, char bottom_p, char left_p, char right_p,
struct glyph_string *s)
/* --------------------------------------------------------------------------
@ -3722,27 +3722,27 @@ larger if there are taller display elements (e.g., characters
/* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
/* top */
sr.size.height = thickness;
sr.size.height = hthickness;
if (top_p) NSRectFill (sr);
/* left */
sr.size.height = r.size.height;
sr.size.width = thickness;
sr.size.width = vthickness;
if (left_p) NSRectFill (sr);
[(raised_p ? darkCol : lightCol) set];
/* bottom */
sr.size.width = r.size.width;
sr.size.height = thickness;
sr.origin.y += r.size.height - thickness;
sr.size.height = hthickness;
sr.origin.y += r.size.height - hthickness;
if (bottom_p) NSRectFill (sr);
/* right */
sr.size.height = r.size.height;
sr.origin.y = r.origin.y;
sr.size.width = thickness;
sr.origin.x += r.size.width - thickness;
sr.size.width = vthickness;
sr.origin.x += r.size.width - vthickness;
if (right_p) NSRectFill (sr);
}
@ -3758,7 +3758,7 @@ Function modeled after x_draw_glyph_string_box ().
char left_p, right_p;
struct glyph *last_glyph;
NSRect r;
int thickness;
int hthickness, vthickness;
struct face *face;
if (s->hl == DRAW_MOUSE_FACE)
@ -3771,7 +3771,8 @@ Function modeled after x_draw_glyph_string_box ().
else
face = s->face;
thickness = face->box_line_width;
vthickness = face->box_vertical_line_width;
hthickness = face->box_horizontal_line_width;
NSTRACE ("ns_dumpglyphs_box_or_relief");
@ -3796,14 +3797,15 @@ Function modeled after x_draw_glyph_string_box ().
/* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
{
ns_draw_box (r, abs (thickness),
ns_draw_box (r, abs (hthickness), abs (vthickness),
ns_lookup_indexed_color (face->box_color, s->f),
left_p, right_p);
left_p, right_p);
}
else
{
ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
1, 1, left_p, right_p, s);
ns_draw_relief (r, abs (hthickness), abs (vthickness),
s->face->box == FACE_RAISED_BOX,
1, 1, left_p, right_p, s);
}
}
@ -3819,7 +3821,7 @@ Function modeled after x_draw_glyph_string_box ().
if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
{
int box_line_width = max (s->face->box_line_width, 0);
int box_line_width = max (s->face->box_horizontal_line_width, 0);
if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
/* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
dimensions, since the actual glyphs might be much
@ -3870,7 +3872,7 @@ Function modeled after x_draw_glyph_string_box ().
-------------------------------------------------------------------------- */
{
EmacsImage *img = s->img->pixmap;
int box_line_vwidth = max (s->face->box_line_width, 0);
int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
int bg_x, bg_y, bg_height;
int th;
@ -3883,7 +3885,7 @@ Function modeled after x_draw_glyph_string_box ().
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p && s->slice.x == 0)
x += abs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
bg_x = x;
bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
@ -4003,7 +4005,7 @@ Function modeled after x_draw_glyph_string_box ().
r.origin.y = y - th;
r.size.width = s->slice.width + 2*th-1;
r.size.height = s->slice.height + 2*th-1;
ns_draw_relief (r, th, raised_p,
ns_draw_relief (r, th, th, raised_p,
s->slice.y == 0,
s->slice.y + s->slice.height == s->img->height,
s->slice.x == 0,
@ -4017,7 +4019,7 @@ Function modeled after x_draw_glyph_string_box ().
{
int thickness = abs (s->img->relief);
if (thickness == 0) thickness = 1;
ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
ns_draw_box (br, thickness, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
}
}
@ -4100,7 +4102,7 @@ overwriting cursor (usually when cursor on a tab) */
of S to the right of that box line. */
if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -4126,7 +4128,7 @@ overwriting cursor (usually when cursor on a tab) */
of S to the right of that box line. */
if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -4142,7 +4144,7 @@ overwriting cursor (usually when cursor on a tab) */
if (s->cmp_from == 0)
{
NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1);
ns_draw_box (r, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
ns_draw_box (r, 1, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
}
}
else if (! s->first_glyph->u.cmp.automatic)

View file

@ -888,10 +888,10 @@ static void w32_draw_image_foreground_1 (struct glyph_string *, HBITMAP);
static void w32_clear_glyph_string_rect (struct glyph_string *, int,
int, int, int);
static void w32_draw_relief_rect (struct frame *, int, int, int, int,
int, int, int, int, int, int,
int, int, int, int, int, int, int,
RECT *);
static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
int, bool, bool, RECT *);
int, int, bool, bool, RECT *);
/* Set S->gc to a suitable GC for drawing glyph string S in cursor
@ -1160,7 +1160,7 @@ w32_draw_glyph_string_background (struct glyph_string *s, bool force_p)
shouldn't be drawn in the first place. */
if (!s->background_filled_p)
{
int box_line_width = max (s->face->box_line_width, 0);
int box_line_width = max (s->face->box_horizontal_line_width, 0);
#if 0 /* TODO: stipple */
if (s->stippled_p)
@ -1206,7 +1206,7 @@ w32_draw_glyph_string_foreground (struct glyph_string *s)
of S to the right of that box line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -1264,7 +1264,7 @@ w32_draw_composite_glyph_string_foreground (struct glyph_string *s)
of S to the right of that box line. */
if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -1361,7 +1361,7 @@ w32_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
of S to the right of that box line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -1617,7 +1617,7 @@ w32_setup_relief_colors (struct glyph_string *s)
static void
w32_draw_relief_rect (struct frame *f,
int left_x, int top_y, int right_x, int bottom_y,
int width, int raised_p,
int hwidth, int vwidth, int raised_p,
int top_p, int bot_p, int left_p, int right_p,
RECT *clip_rect)
{
@ -1634,14 +1634,14 @@ w32_draw_relief_rect (struct frame *f,
/* Top. */
if (top_p)
for (i = 0; i < width; ++i)
for (i = 0; i < hwidth; ++i)
w32_fill_area (f, hdc, gc.foreground,
left_x + i * left_p, top_y + i,
right_x - left_x - i * (left_p + right_p ) + 1, 1);
/* Left. */
if (left_p)
for (i = 0; i < width; ++i)
for (i = 0; i < vwidth; ++i)
w32_fill_area (f, hdc, gc.foreground,
left_x + i, top_y + (i + 1) * top_p, 1,
bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@ -1653,14 +1653,14 @@ w32_draw_relief_rect (struct frame *f,
/* Bottom. */
if (bot_p)
for (i = 0; i < width; ++i)
for (i = 0; i < hwidth; ++i)
w32_fill_area (f, hdc, gc.foreground,
left_x + i * left_p, bottom_y - i,
right_x - left_x - i * (left_p + right_p) + 1, 1);
/* Right. */
if (right_p)
for (i = 0; i < width; ++i)
for (i = 0; i < vwidth; ++i)
w32_fill_area (f, hdc, gc.foreground,
right_x - i, top_y + (i + 1) * top_p, 1,
bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@ -1680,31 +1680,31 @@ w32_draw_relief_rect (struct frame *f,
static void
w32_draw_box_rect (struct glyph_string *s,
int left_x, int top_y, int right_x, int bottom_y, int width,
bool left_p, bool right_p, RECT *clip_rect)
int left_x, int top_y, int right_x, int bottom_y, int hwidth,
int vwidth, bool left_p, bool right_p, RECT *clip_rect)
{
w32_set_clip_rectangle (s->hdc, clip_rect);
/* Top. */
w32_fill_area (s->f, s->hdc, s->face->box_color,
left_x, top_y, right_x - left_x + 1, width);
left_x, top_y, right_x - left_x + 1, hwidth);
/* Left. */
if (left_p)
{
w32_fill_area (s->f, s->hdc, s->face->box_color,
left_x, top_y, width, bottom_y - top_y + 1);
left_x, top_y, vwidth, bottom_y - top_y + 1);
}
/* Bottom. */
w32_fill_area (s->f, s->hdc, s->face->box_color,
left_x, bottom_y - width + 1, right_x - left_x + 1, width);
left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
/* Right. */
if (right_p)
{
w32_fill_area (s->f, s->hdc, s->face->box_color,
right_x - width + 1, top_y, width, bottom_y - top_y + 1);
right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
}
w32_set_clip_rectangle (s->hdc, NULL);
@ -1716,7 +1716,7 @@ w32_draw_box_rect (struct glyph_string *s,
static void
w32_draw_glyph_string_box (struct glyph_string *s)
{
int width, left_x, right_x, top_y, bottom_y, last_x;
int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
bool left_p, right_p, raised_p;
struct glyph *last_glyph;
RECT clip_rect;
@ -1730,7 +1730,8 @@ w32_draw_glyph_string_box (struct glyph_string *s)
? s->first_glyph
: s->first_glyph + s->nchars - 1);
width = eabs (s->face->box_line_width);
vwidth = eabs (s->face->box_vertical_line_width);
hwidth = eabs (s->face->box_horizontal_line_width);
raised_p = s->face->box == FACE_RAISED_BOX;
left_x = s->x;
right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@ -1751,13 +1752,13 @@ w32_draw_glyph_string_box (struct glyph_string *s)
get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
left_p, right_p, &clip_rect);
w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
vwidth, left_p, right_p, &clip_rect);
else
{
w32_setup_relief_colors (s);
w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
width, raised_p, 1, 1, left_p, right_p, &clip_rect);
w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
vwidth, raised_p, 1, 1, left_p, right_p, &clip_rect);
}
}
@ -1795,7 +1796,7 @@ w32_draw_image_foreground (struct glyph_string *s)
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += eabs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
@ -1982,7 +1983,7 @@ w32_draw_image_relief (struct glyph_string *s)
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += eabs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
@ -2034,7 +2035,7 @@ w32_draw_image_relief (struct glyph_string *s)
w32_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
w32_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
top_p, bot_p, left_p, right_p, &r);
}
@ -2054,7 +2055,7 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += eabs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
@ -2167,8 +2168,8 @@ static void
w32_draw_image_glyph_string (struct glyph_string *s)
{
int x, y;
int box_line_hwidth = eabs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
int height, width;
HBITMAP pixmap = 0;

View file

@ -2061,8 +2061,8 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
{
if (face->font)
height = normal_char_height (face->font, -1);
if (face->box_line_width > 0)
height += 2 * face->box_line_width;
if (face->box_horizontal_line_width > 0)
height += 2 * face->box_horizontal_line_width;
}
}
@ -28900,18 +28900,21 @@ produce_image_glyph (struct it *it)
if (face->box != FACE_NO_BOX)
{
if (face->box_line_width > 0)
if (face->box_horizontal_line_width > 0)
{
if (slice.y == 0)
it->ascent += face->box_line_width;
it->ascent += face->box_horizontal_line_width;
if (slice.y + slice.height == img->height)
it->descent += face->box_line_width;
it->descent += face->box_horizontal_line_width;
}
if (it->start_of_box_run_p && slice.x == 0)
it->pixel_width += eabs (face->box_line_width);
if (it->end_of_box_run_p && slice.x + slice.width == img->width)
it->pixel_width += eabs (face->box_line_width);
if (face->box_vertical_line_width > 0)
{
if (it->start_of_box_run_p && slice.x == 0)
it->pixel_width += face->box_vertical_line_width;
if (it->end_of_box_run_p && slice.x + slice.width == img->width)
it->pixel_width += face->box_vertical_line_width;
}
}
take_vertical_position_into_account (it);
@ -29009,15 +29012,18 @@ produce_xwidget_glyph (struct it *it)
if (face->box != FACE_NO_BOX)
{
if (face->box_line_width > 0)
if (face->box_horizontal_line_width > 0)
{
it->ascent += face->box_line_width;
it->descent += face->box_line_width;
it->ascent += face->box_horizontal_line_width;
it->descent += face->box_horizontal_line_width;
}
if (it->start_of_box_run_p)
it->pixel_width += eabs (face->box_line_width);
it->pixel_width += eabs (face->box_line_width);
if (face->box_vertical_line_width > 0)
{
if (it->start_of_box_run_p)
it->pixel_width += face->box_vertical_line_width;
it->pixel_width += face->box_vertical_line_width;
}
}
take_vertical_position_into_account (it);
@ -29780,6 +29786,31 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
}
/* If face has a box, add the box thickness to the character
height. If character has a box line to the left and/or
right, add the box line width to the character's width. */
#define IT_APPLY_FACE_BOX(it, face) \
do { \
if (face->box != FACE_NO_BOX) \
{ \
int thick = face->box_horizontal_line_width; \
if (thick > 0) \
{ \
it->ascent += thick; \
it->descent += thick; \
} \
\
thick = face->box_vertical_line_width; \
if (thick > 0) \
{ \
if (it->start_of_box_run_p) \
it->pixel_width += thick; \
if (it->end_of_box_run_p) \
it->pixel_width += thick; \
} \
} \
} while (false)
/* RIF:
Produce glyphs/get display metrics for the display element IT is
loaded with. See the description of struct it in dispextern.h
@ -29895,26 +29926,7 @@ gui_produce_glyphs (struct it *it)
if (stretched_p)
it->pixel_width *= XFLOATINT (it->space_width);
/* If face has a box, add the box thickness to the character
height. If character has a box line to the left and/or
right, add the box line width to the character's width. */
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
if (thick > 0)
{
it->ascent += thick;
it->descent += thick;
}
else
thick = -thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->pixel_width += thick;
}
IT_APPLY_FACE_BOX(it, face);
/* If face has an overline, add the height of the overline
(1 pixel) and a 1 pixel margin to the character height. */
@ -30029,10 +30041,10 @@ gui_produce_glyphs (struct it *it)
if ((it->max_ascent > 0 || it->max_descent > 0)
&& face->box != FACE_NO_BOX
&& face->box_line_width > 0)
&& face->box_horizontal_line_width > 0)
{
it->ascent += face->box_line_width;
it->descent += face->box_line_width;
it->ascent += face->box_horizontal_line_width;
it->descent += face->box_horizontal_line_width;
}
if (!NILP (height)
&& XFIXNUM (height) > it->ascent + it->descent)
@ -30439,23 +30451,7 @@ gui_produce_glyphs (struct it *it)
it->pixel_width = cmp->pixel_width;
it->ascent = it->phys_ascent = cmp->ascent;
it->descent = it->phys_descent = cmp->descent;
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
if (thick > 0)
{
it->ascent += thick;
it->descent += thick;
}
else
thick = - thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->pixel_width += thick;
}
IT_APPLY_FACE_BOX(it, face);
/* If face has an overline, add the height of the overline
(1 pixel) and a 1 pixel margin to the character height. */
@ -30489,23 +30485,8 @@ gui_produce_glyphs (struct it *it)
it->glyph_row->contains_overlapping_glyphs_p = true;
it->ascent = it->phys_ascent = metrics.ascent;
it->descent = it->phys_descent = metrics.descent;
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
IT_APPLY_FACE_BOX(it, face);
if (thick > 0)
{
it->ascent += thick;
it->descent += thick;
}
else
thick = - thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->pixel_width += thick;
}
/* If face has an overline, add the height of the overline
(1 pixel) and a 1 pixel margin to the character height. */
if (face->overline_p)

View file

@ -3128,6 +3128,8 @@ FRAME 0 means change the face on all frames, and change the default
valid_p = XFIXNUM (value) != 0;
else if (STRINGP (value))
valid_p = SCHARS (value) > 0;
else if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value)))
valid_p = true;
else if (CONSP (value))
{
Lisp_Object tem;
@ -3146,7 +3148,9 @@ FRAME 0 means change the face on all frames, and change the default
if (EQ (k, QCline_width))
{
if (!FIXNUMP (v) || XFIXNUM (v) == 0)
if ((!CONSP(v) || !FIXNUMP (XCAR (v)) || XFIXNUM (XCAR (v)) == 0
|| !FIXNUMP (XCDR (v)) || XFIXNUM (XCDR (v)) == 0)
&& (!FIXNUMP (v) || XFIXNUM (v) == 0))
break;
}
else if (EQ (k, QCcolor))
@ -5815,7 +5819,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
LFACE_BOX_INDEX);
face->box = FACE_SIMPLE_BOX;
face->box_line_width = 1;
face->box_vertical_line_width = face->box_horizontal_line_width = 1;
}
else if (FIXNUMP (box))
{
@ -5823,10 +5827,20 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face. */
eassert (XFIXNUM (box) != 0);
face->box = FACE_SIMPLE_BOX;
face->box_line_width = XFIXNUM (box);
face->box_vertical_line_width = eabs(XFIXNUM (box));
face->box_horizontal_line_width = XFIXNUM (box);
face->box_color = face->foreground;
face->box_color_defaulted_p = true;
}
else if (CONSP (box) && FIXNUMP (XCAR (box)) && FIXNUMP (XCDR (box)))
{
/* `(VWIDTH . HWIDTH)'. */
face->box = FACE_SIMPLE_BOX;
face->box_color = face->foreground;
face->box_color_defaulted_p = true;
face->box_vertical_line_width = XFIXNUM (XCAR (box));
face->box_horizontal_line_width = XFIXNUM (XCDR (box));
}
else if (CONSP (box))
{
/* `(:width WIDTH :color COLOR :shadow SHADOW)'. SHADOW
@ -5834,7 +5848,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face->box = FACE_SIMPLE_BOX;
face->box_color = face->foreground;
face->box_color_defaulted_p = true;
face->box_line_width = 1;
face->box_vertical_line_width = face->box_horizontal_line_width = 1;
while (CONSP (box))
{
@ -5850,8 +5864,14 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
if (EQ (keyword, QCline_width))
{
if (FIXNUMP (value) && XFIXNUM (value) != 0)
face->box_line_width = XFIXNUM (value);
if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value))) {
face->box_vertical_line_width = XFIXNUM (XCAR (value));
face->box_horizontal_line_width = XFIXNUM (XCDR (value));
}
else if (FIXNUMP (value) && XFIXNUM (value) != 0) {
face->box_vertical_line_width = eabs (XFIXNUM (value));
face->box_horizontal_line_width = XFIXNUM (value);
}
}
else if (EQ (keyword, QCcolor))
{

View file

@ -1754,7 +1754,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
shouldn't be drawn in the first place. */
if (!s->background_filled_p)
{
int box_line_width = max (s->face->box_line_width, 0);
int box_line_width = max (s->face->box_horizontal_line_width, 0);
if (s->stippled_p)
{
@ -1799,7 +1799,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
of S to the right of that box line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -1849,7 +1849,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
if (!(s->for_overlaps
|| (s->background_filled_p && s->hl != DRAW_CURSOR)))
{
int box_line_width = max (s->face->box_line_width, 0);
int box_line_width = max (s->face->box_horizontal_line_width, 0);
if (s->stippled_p)
{
@ -1893,7 +1893,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
of S to the right of that box line. */
if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -2004,7 +2004,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
of S to the right of that box line. */
if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
x = s->x + max (s->face->box_vertical_line_width, 0);
else
x = s->x;
@ -2769,7 +2769,7 @@ x_setup_relief_colors (struct glyph_string *s)
static void
x_draw_relief_rect (struct frame *f,
int left_x, int top_y, int right_x, int bottom_y,
int width, bool raised_p, bool top_p, bool bot_p,
int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
bool left_p, bool right_p,
XRectangle *clip_rect)
{
@ -2794,7 +2794,7 @@ x_draw_relief_rect (struct frame *f,
if (left_p)
{
x_fill_rectangle (f, top_left_gc, left_x, top_y,
width, bottom_y + 1 - top_y);
vwidth, bottom_y + 1 - top_y);
if (top_p)
corners |= 1 << CORNER_TOP_LEFT;
if (bot_p)
@ -2802,8 +2802,8 @@ x_draw_relief_rect (struct frame *f,
}
if (right_p)
{
x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
width, bottom_y + 1 - top_y);
x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
vwidth, bottom_y + 1 - top_y);
if (top_p)
corners |= 1 << CORNER_TOP_RIGHT;
if (bot_p)
@ -2813,25 +2813,25 @@ x_draw_relief_rect (struct frame *f,
{
if (!right_p)
x_fill_rectangle (f, top_left_gc, left_x, top_y,
right_x + 1 - left_x, width);
right_x + 1 - left_x, hwidth);
else
x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
right_x + 1 - left_x, width, 1);
right_x + 1 - left_x, hwidth, 1);
}
if (bot_p)
{
if (!left_p)
x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
right_x + 1 - left_x, width);
x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
right_x + 1 - left_x, hwidth);
else
x_fill_trapezoid_for_relief (f, bottom_right_gc,
left_x, bottom_y + 1 - width,
right_x + 1 - left_x, width, 0);
left_x, bottom_y + 1 - hwidth,
right_x + 1 - left_x, hwidth, 0);
}
if (left_p && width != 1)
if (left_p && vwidth > 1)
x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
1, bottom_y + 1 - top_y);
if (top_p && width != 1)
if (top_p && hwidth > 1)
x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
right_x + 1 - left_x, 1);
if (corners)
@ -2865,12 +2865,12 @@ x_draw_relief_rect (struct frame *f,
/* Top. */
if (top_p)
{
if (width == 1)
if (hwidth == 1)
XDrawLine (dpy, drawable, gc,
left_x + left_p, top_y,
right_x + !right_p, top_y);
for (i = 1; i < width; ++i)
for (i = 1; i < hwidth; ++i)
XDrawLine (dpy, drawable, gc,
left_x + i * left_p, top_y + i,
right_x + 1 - i * right_p, top_y + i);
@ -2879,13 +2879,10 @@ x_draw_relief_rect (struct frame *f,
/* Left. */
if (left_p)
{
if (width == 1)
if (vwidth == 1)
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
x_clear_area(f, left_x, top_y, 1, 1);
x_clear_area(f, left_x, bottom_y, 1, 1);
for (i = (width > 1 ? 1 : 0); i < width; ++i)
for (i = 1; i < vwidth; ++i)
XDrawLine (dpy, drawable, gc,
left_x + i, top_y + (i + 1) * top_p,
left_x + i, bottom_y + 1 - (i + 1) * bot_p);
@ -2898,26 +2895,25 @@ x_draw_relief_rect (struct frame *f,
gc = f->output_data.x->white_relief.gc;
XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
if (width > 1)
{
/* Outermost top line. */
if (top_p)
XDrawLine (dpy, drawable, gc,
left_x + left_p, top_y,
right_x + !right_p, top_y);
/* Outermost top line. */
if (top_p && hwidth > 1)
XDrawLine (dpy, drawable, gc,
left_x + left_p, top_y,
right_x + !right_p, top_y);
/* Outermost left line. */
if (left_p)
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
}
/* Outermost left line. */
if (left_p && vwidth > 1)
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
/* Bottom. */
if (bot_p)
{
XDrawLine (dpy, drawable, gc,
left_x + left_p, bottom_y,
right_x + !right_p, bottom_y);
for (i = 1; i < width; ++i)
if (hwidth >= 1)
XDrawLine (dpy, drawable, gc,
left_x + left_p, bottom_y,
right_x + !right_p, bottom_y);
for (i = 1; i < hwidth; ++i)
XDrawLine (dpy, drawable, gc,
left_x + i * left_p, bottom_y - i,
right_x + 1 - i * right_p, bottom_y - i);
@ -2926,9 +2922,7 @@ x_draw_relief_rect (struct frame *f,
/* Right. */
if (right_p)
{
x_clear_area(f, right_x, top_y, 1, 1);
x_clear_area(f, right_x, bottom_y, 1, 1);
for (i = 0; i < width; ++i)
for (i = 0; i < vwidth; ++i)
XDrawLine (dpy, drawable, gc,
right_x - i, top_y + (i + 1) * top_p,
right_x - i, bottom_y + 1 - (i + 1) * bot_p);
@ -2949,8 +2943,8 @@ x_draw_relief_rect (struct frame *f,
static void
x_draw_box_rect (struct glyph_string *s,
int left_x, int top_y, int right_x, int bottom_y, int width,
bool left_p, bool right_p, XRectangle *clip_rect)
int left_x, int top_y, int right_x, int bottom_y, int hwidth,
int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
{
Display *display = FRAME_X_DISPLAY (s->f);
XGCValues xgcv;
@ -2961,21 +2955,21 @@ x_draw_box_rect (struct glyph_string *s,
/* Top. */
x_fill_rectangle (s->f, s->gc,
left_x, top_y, right_x - left_x + 1, width);
left_x, top_y, right_x - left_x + 1, hwidth);
/* Left. */
if (left_p)
x_fill_rectangle (s->f, s->gc,
left_x, top_y, width, bottom_y - top_y + 1);
left_x, top_y, vwidth, bottom_y - top_y + 1);
/* Bottom. */
x_fill_rectangle (s->f, s->gc,
left_x, bottom_y - width + 1, right_x - left_x + 1, width);
left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
/* Right. */
if (right_p)
x_fill_rectangle (s->f, s->gc,
right_x - width + 1, top_y, width, bottom_y - top_y + 1);
right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
XSetForeground (display, s->gc, xgcv.foreground);
x_reset_clip_rectangles (s->f, s->gc);
@ -2987,7 +2981,7 @@ x_draw_box_rect (struct glyph_string *s,
static void
x_draw_glyph_string_box (struct glyph_string *s)
{
int width, left_x, right_x, top_y, bottom_y, last_x;
int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
bool raised_p, left_p, right_p;
struct glyph *last_glyph;
XRectangle clip_rect;
@ -3001,7 +2995,8 @@ x_draw_glyph_string_box (struct glyph_string *s)
? s->first_glyph
: s->first_glyph + s->nchars - 1);
width = eabs (s->face->box_line_width);
vwidth = eabs (s->face->box_vertical_line_width);
hwidth = eabs (s->face->box_horizontal_line_width);
raised_p = s->face->box == FACE_RAISED_BOX;
left_x = s->x;
right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
@ -3022,13 +3017,13 @@ x_draw_glyph_string_box (struct glyph_string *s)
get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
left_p, right_p, &clip_rect);
x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
vwidth, left_p, right_p, &clip_rect);
else
{
x_setup_relief_colors (s);
x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
width, raised_p, true, true, left_p, right_p,
x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
vwidth, raised_p, true, true, left_p, right_p,
&clip_rect);
}
}
@ -3086,7 +3081,7 @@ x_draw_image_foreground (struct glyph_string *s)
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += eabs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
@ -3205,7 +3200,7 @@ x_draw_image_relief (struct glyph_string *s)
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += eabs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
@ -3273,7 +3268,7 @@ x_draw_image_relief (struct glyph_string *s)
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
top_p, bot_p, left_p, right_p, &r);
}
@ -3292,7 +3287,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += eabs (s->face->box_line_width);
x += max (s->face->box_vertical_line_width, 0);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
@ -3394,8 +3389,8 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
static void
x_draw_image_glyph_string (struct glyph_string *s)
{
int box_line_hwidth = eabs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
int height;
#ifndef USE_CAIRO
Display *display = FRAME_X_DISPLAY (s->f);