[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] /srv/bzr/emacs/trunk r108632: Merge implmentation of wave-
From: |
Alp Aker |
Subject: |
[Emacs-diffs] /srv/bzr/emacs/trunk r108632: Merge implmentation of wave-style underline face attribute (debbugs.gnu.org/10736). |
Date: |
Sat, 16 Jun 2012 20:35:30 -0400 |
User-agent: |
Bazaar (2.5.0) |
------------------------------------------------------------
revno: 108632 [merge]
committer: Alp Aker <address@hidden>
branch nick: trunk
timestamp: Sat 2012-06-16 20:35:30 -0400
message:
Merge implmentation of wave-style underline face attribute
(debbugs.gnu.org/10736).
modified:
ChangeLog
doc/lispref/display.texi
lisp/ChangeLog
lisp/cus-face.el
lisp/faces.el
src/ChangeLog
src/dispextern.h
src/nsterm.m
src/w32term.c
src/xfaces.c
src/xterm.c
=== modified file 'ChangeLog'
--- a/ChangeLog 2012-06-13 13:40:48 +0000
+++ b/ChangeLog 2012-06-17 00:32:36 +0000
@@ -1,3 +1,8 @@
+2012-06-16 Aurelien Aptel <address@hidden>
+
+ * doc/lispref/display.texi: Document wave-style underline
+ face attribute.
+
2012-06-13 Andreas Schwab <address@hidden>
* configure.in: Rename --enable-use-lisp-union-type to
=== modified file 'doc/lispref/display.texi'
--- a/doc/lispref/display.texi 2012-06-11 14:42:55 +0000
+++ b/doc/lispref/display.texi 2012-06-17 00:32:36 +0000
@@ -2130,10 +2130,32 @@
name, or a hexadecimal color specification. @xref{Color Names}.
@item :underline
-Whether or not characters should be underlined, and in what color. If
-the value is @code{t}, underlining uses the foreground color of the
-face. If the value is a string, underlining uses that color. The
-value @code{nil} means do not underline.
+Whether or not characters should be underlined, and in what
+color. Here are the possible values of the @code{:underline}
+attribute, and what they mean:
+
address@hidden @asis
address@hidden @code{nil}
+Don't underline.
+
address@hidden @code{t}
+Underline with the foreground color of the face.
+
address@hidden @var{color}
+Underline in color @var{color}.
+
address@hidden @code{(:color @var{color} :style @var{style})}
+If @var{color} is a string, underline in it.
+If @var{color} is @code{foreground-color}, underline with the
+foreground color of the face.
+
+If @var{style} is @code{wave} underline with a wave.
+If @var{style} is @code{line} underline with a line.
+
+If the attribute @code{:color} is omited, underline with the
+foreground color of the face.
+If the attribute @code{:style} is omited, underline with a line.
address@hidden table
@item :overline
Whether or not characters should be overlined, and in what color.
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog 2012-06-16 17:45:09 +0000
+++ b/lisp/ChangeLog 2012-06-17 00:32:36 +0000
@@ -1,3 +1,10 @@
+2012-06-16 Aurelien Aptel <address@hidden>
+
+ * cus-face.el (custom-face-attributes): Add wave-style underline
+ attribute.
+ * faces.el (set-face-attribute): Update docstring to describe
+ wave-style underline attribute.
+
2012-06-16 Chong Yidong <address@hidden>
* term/xterm.el (terminal-init-xterm): Discard input before
=== modified file 'lisp/cus-face.el'
--- a/lisp/cus-face.el 2012-01-19 07:21:25 +0000
+++ b/lisp/cus-face.el 2012-06-17 00:32:36 +0000
@@ -135,8 +135,13 @@
(choice :tag "Underline"
:help-echo "Control text underlining."
(const :tag "Off" nil)
- (const :tag "On" t)
- (color :tag "Colored")))
+ (list :tag "On"
+ (const :format "" :value :color)
+ (choice :tag "Color" (const :tag "Foreground Color"
foreground-color) color)
+ (const :format "" :value :style)
+ (choice :tag "Style"
+ (const :tag "Line" line)
+ (const :tag "Wave" wave)))))
(:overline
(choice :tag "Overline"
=== modified file 'lisp/faces.el'
--- a/lisp/faces.el 2012-06-08 16:39:49 +0000
+++ b/lisp/faces.el 2012-06-17 00:32:36 +0000
@@ -623,10 +623,21 @@
`:underline'
-VALUE specifies whether characters in FACE should be underlined. If
-VALUE is t, underline with foreground color of the face. If VALUE is
-a string, underline with that color. If VALUE is nil, explicitly
-don't underline.
+VALUE specifies whether characters in FACE should be underlined.
+If VALUE is t, underline with foreground color of the face.
+If VALUE is a string, underline with that color.
+If VALUE is nil, explicitly don't underline.
+
+Otherwise, VALUE must be a property list of the form:
+
+`(:color COLOR :style STYLE)'.
+
+COLOR can be a either a color name string or `foreground-color'.
+STYLE can be either `line' or `wave'.
+If a keyword/value pair is missing from the property list, a
+default value will be used for the value.
+The default value of COLOR is the foreground color of the face.
+The default value of STYLE is `line'.
`:overline'
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2012-06-16 13:44:20 +0000
+++ b/src/ChangeLog 2012-06-17 00:32:36 +0000
@@ -1,3 +1,20 @@
+2012-06-16 Aurelien Aptel <address@hidden>
+
+ Implement wave-style variant of underlining.
+ * dispextern.h (face_underline_type): New enum.
+ (face): Add field for underline type.
+ * nsterm.m (ns_draw_underwave): New function.
+ (ns_draw_text_decoration): Use it.
+ * w32term.c (w32_restore_glyph_string_clip, w32_draw_underwave):
+ New functions.
+ (x_draw_glyph_string): Use them.
+ * xfaces.c (Qline, Qwave): New Lisp objects.
+ (check_lface_attrs, merge_face_ref)
+ (Finternal_set_lisp_face_attribute, realize_x_face): Handle
+ wave-style underline face attributes.
+ * xterm.c (x_draw_underwave): New function.
+ (x_draw_glyph_string): Use it.
+
2012-06-16 Juanma Barranquero <address@hidden>
* makefile.w32-in ($(BLD)/emacs.$(O), $(BLD)/fringe.$(O))
=== modified file 'src/dispextern.h'
--- a/src/dispextern.h 2012-06-10 13:20:58 +0000
+++ b/src/dispextern.h 2012-06-17 00:32:36 +0000
@@ -1510,6 +1510,13 @@
FACE_SUNKEN_BOX
};
+/* Underline type. */
+
+enum face_underline_type
+{
+ FACE_UNDER_LINE,
+ FACE_UNDER_WAVE
+};
/* Structure describing a realized face.
@@ -1585,6 +1592,9 @@
drawing shadows. */
unsigned use_box_color_for_shadows_p : 1;
+ /* Style of underlining. */
+ enum face_underline_type underline_type;
+
/* Non-zero if text in this face should be underlined, overlined,
strike-through or have a box drawn around it. */
unsigned underline_p : 1;
=== modified file 'src/nsterm.m'
--- a/src/nsterm.m 2012-05-26 21:23:28 +0000
+++ b/src/nsterm.m 2012-06-17 00:32:36 +0000
@@ -2595,6 +2595,60 @@
return n;
}
+/* --------------------------------------------------------------------
+ Draw a wavy line under glyph string s. The wave fills wave_height
+ pixels from y.
+
+ x wave_length = 3
+ --
+ y * * * * *
+ |* * * * * * * * *
+ wave_height = 3 | * * * *
+ --------------------------------------------------------------------- */
+
+static void
+ns_draw_underwave (struct glyph_string *s, CGFloat width, CGFloat x)
+{
+ int wave_height = 3, wave_length = 3;
+ int y, dx, dy, odd, xmax;
+ NSPoint a, b;
+ NSRect waveClip;
+
+ dx = wave_length;
+ dy = wave_height - 1;
+ y = s->ybase + 1;
+ xmax = x + width;
+
+ /* Find and set clipping rectangle */
+ waveClip = NSMakeRect (x, y, width, wave_height);
+ [[NSGraphicsContext currentContext] saveGraphicsState];
+ NSRectClip (waveClip);
+
+ /* Draw the waves */
+ a.x = x - ((int)(x) % dx);
+ b.x = a.x + dx;
+ odd = (int)(a.x/dx) % 2;
+ a.y = b.y = y;
+
+ if (odd)
+ a.y += dy;
+ else
+ b.y += dy;
+
+ while (a.x <= xmax)
+ {
+ [NSBezierPath strokeLineFromPoint:a toPoint:b];
+ a.x = b.x, a.y = b.y;
+ b.x += dx, b.y = y + odd*dy;
+ odd = !odd;
+ }
+
+ /* Restore previous clipping rectangle(s) */
+ [[NSGraphicsContext currentContext] restoreGraphicsState];
+}
+
+
+
void
ns_draw_text_decoration (struct glyph_string *s, struct face *face,
NSColor *defaultCol, CGFloat width, CGFloat x)
@@ -2608,63 +2662,75 @@
/* Do underline. */
if (face->underline_p)
{
- NSRect r;
- unsigned long thickness, position;
-
- /* If the prev was underlined, match its appearance. */
- if (s->prev && s->prev->face->underline_p
- && s->prev->underline_thickness > 0)
- {
- thickness = s->prev->underline_thickness;
- position = s->prev->underline_position;
- }
- else
- {
- struct font *font;
- unsigned long descent;
-
- font=s->font;
- descent = s->y + s->height - s->ybase;
-
- /* Use underline thickness of font, defaulting to 1. */
- thickness = (font && font->underline_thickness > 0)
- ? font->underline_thickness : 1;
-
- /* Determine the offset of underlining from the baseline. */
- if (x_underline_at_descent_line)
- position = descent - thickness;
- else if (x_use_underline_position_properties
- && font && font->underline_position >= 0)
- position = font->underline_position;
- else if (font)
- position = lround (font->descent / 2);
- else
- position = underline_minimum_offset;
-
- position = max (position, underline_minimum_offset);
-
- /* Ensure underlining is not cropped. */
- if (descent <= position)
- {
- position = descent - 1;
- thickness = 1;
- }
- else if (descent < position + thickness)
- thickness = 1;
- }
-
- s->underline_thickness = thickness;
- s->underline_position = position;
-
- r = NSMakeRect (x, s->ybase + position, width, thickness);
-
- if (face->underline_defaulted_p)
- [defaultCol set];
- else
- [ns_lookup_indexed_color (face->underline_color, s->f) set];
- NSRectFill (r);
+ if (s->face->underline_type == FACE_UNDER_WAVE)
+ {
+ if (face->underline_defaulted_p)
+ [defaultCol set];
+ else
+ [ns_lookup_indexed_color (face->underline_color, s->f) set];
+
+ ns_draw_underwave (s, width, x);
+ }
+ else if (s->face->underline_type == FACE_UNDER_LINE)
+ {
+
+ NSRect r;
+ unsigned long thickness, position;
+
+ /* If the prev was underlined, match its appearance. */
+ if (s->prev && s->prev->face->underline_p
+ && s->prev->underline_thickness > 0)
+ {
+ thickness = s->prev->underline_thickness;
+ position = s->prev->underline_position;
+ }
+ else
+ {
+ struct font *font;
+ unsigned long descent;
+
+ font=s->font;
+ descent = s->y + s->height - s->ybase;
+
+ /* Use underline thickness of font, defaulting to 1. */
+ thickness = (font && font->underline_thickness > 0)
+ ? font->underline_thickness : 1;
+
+ /* Determine the offset of underlining from the baseline. */
+ if (x_underline_at_descent_line)
+ position = descent - thickness;
+ else if (x_use_underline_position_properties
+ && font && font->underline_position >= 0)
+ position = font->underline_position;
+ else if (font)
+ position = lround (font->descent / 2);
+ else
+ position = underline_minimum_offset;
+
+ position = max (position, underline_minimum_offset);
+
+ /* Ensure underlining is not cropped. */
+ if (descent <= position)
+ {
+ position = descent - 1;
+ thickness = 1;
+ }
+ else if (descent < position + thickness)
+ thickness = 1;
+ }
+
+ s->underline_thickness = thickness;
+ s->underline_position = position;
+
+ r = NSMakeRect (x, s->ybase + position, width, thickness);
+
+ if (face->underline_defaulted_p)
+ [defaultCol set];
+ else
+ [ns_lookup_indexed_color (face->underline_color, s->f) set];
+ NSRectFill (r);
+ }
}
-
/* Do overline. We follow other terms in using a thickness of 1
and ignoring overline_margin. */
if (face->overline_p)
=== modified file 'src/w32term.c'
--- a/src/w32term.c 2012-06-13 13:40:48 +0000
+++ b/src/w32term.c 2012-06-17 00:32:36 +0000
@@ -313,6 +313,94 @@
SelectClipRgn (hdc, NULL);
}
+/* Restore clipping rectangle in S */
+static void
+w32_restore_glyph_string_clip (struct glyph_string *s)
+{
+ RECT *r = s->clip;
+ int n = s->num_clips;
+
+ if (n == 1)
+ w32_set_clip_rectangle (s->hdc, r);
+ else if (n > 1)
+ {
+ HRGN clip1 = CreateRectRgnIndirect (r);
+ HRGN clip2 = CreateRectRgnIndirect (r + 1);
+ if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
+ SelectClipRgn (s->hdc, clip1);
+ DeleteObject (clip1);
+ DeleteObject (clip2);
+ }
+}
+
+/*
+ Draw a wavy line under S. The wave fills wave_height pixels from y0.
+
+ x0 wave_length = 2
+ --
+ y0 * * * * *
+ |* * * * * * * * *
+ wave_height = 3 | * * * *
+
+*/
+
+void
+w32_draw_underwave (struct glyph_string *s, COLORREF color)
+{
+ int wave_height = 2, wave_length = 3;
+ int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
+ XRectangle wave_clip, string_clip, final_clip;
+ RECT w32_final_clip, w32_string_clip;
+ HPEN hp, oldhp;
+
+ dx = wave_length;
+ dy = wave_height - 1;
+ x0 = s->x;
+ y0 = s->ybase + 1;
+ width = s->width;
+ xmax = x0 + width;
+
+ /* Find and set clipping rectangle */
+
+ wave_clip = (XRectangle){ x0, y0, width, wave_height };
+ get_glyph_string_clip_rect (s, &w32_string_clip);
+ CONVERT_TO_XRECT (string_clip, w32_string_clip);
+
+ if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
+ return;
+
+ hp = CreatePen (PS_SOLID, 0, color);
+ oldhp = SelectObject (s->hdc, hp);
+ CONVERT_FROM_XRECT (final_clip, w32_final_clip);
+ w32_set_clip_rectangle (s->hdc, &w32_final_clip);
+
+ /* Draw the waves */
+
+ x1 = x0 - (x0 % dx);
+ x2 = x1 + dx;
+ odd = (x1/dx) % 2;
+ y1 = y2 = y0;
+
+ if (odd)
+ y1 += dy;
+ else
+ y2 += dy;
+
+ MoveToEx (s->hdc, x1, y1, NULL);
+
+ while (x1 <= xmax)
+ {
+ LineTo (s->hdc, x2, y2);
+ x1 = x2, y1 = y2;
+ x2 += dx, y2 = y0 + odd*dy;
+ odd = !odd;
+ }
+
+ /* Restore previous pen and clipping rectangle(s) */
+ w32_restore_glyph_string_clip (s);
+ SelectObject (s->hdc, oldhp);
+ DeleteObject (hp);
+}
/* Draw a hollow rectangle at the specified position. */
void
@@ -2347,60 +2435,74 @@
/* Draw underline. */
if (s->face->underline_p)
{
- unsigned long thickness, position;
- int y;
-
- if (s->prev && s->prev->face->underline_p)
- {
- /* We use the same underline style as the previous one. */
- thickness = s->prev->underline_thickness;
- position = s->prev->underline_position;
- }
- else
- {
- /* Get the underline thickness. Default is 1 pixel. */
- if (s->font && s->font->underline_thickness > 0)
- thickness = s->font->underline_thickness;
- else
- thickness = 1;
- if (x_underline_at_descent_line)
- position = (s->height - thickness) - (s->ybase - s->y);
- else
- {
- /* Get the underline position. This is the recommended
- vertical offset in pixels from the baseline to the top of
- the underline. This is a signed value according to the
- specs, and its default is
-
- ROUND ((maximum_descent) / 2), with
- ROUND (x) = floor (x + 0.5) */
-
- if (x_use_underline_position_properties
- && s->font && s->font->underline_position >= 0)
- position = s->font->underline_position;
- else if (s->font)
- position = (s->font->descent + 1) / 2;
- }
- position = max (position, underline_minimum_offset);
- }
- /* Check the sanity of thickness and position. We should
- avoid drawing underline out of the current line area. */
- if (s->y + s->height <= s->ybase + position)
- position = (s->height - 1) - (s->ybase - s->y);
- if (s->y + s->height < s->ybase + position + thickness)
- thickness = (s->y + s->height) - (s->ybase + position);
- s->underline_thickness = thickness;
- s->underline_position =position;
- y = s->ybase + position;
- if (s->face->underline_defaulted_p)
- {
- w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
- y, s->width, 1);
- }
- else
- {
- w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
- y, s->width, 1);
+ if (s->face->underline_type == FACE_UNDER_WAVE)
+ {
+ COLORREF color;
+
+ if (s->face->underline_defaulted_p)
+ color = s->gc->foreground;
+ else
+ color = s->face->underline_color;
+
+ w32_draw_underwave (s, color);
+ }
+ else if (s->face->underline_type == FACE_UNDER_LINE)
+ {
+ unsigned long thickness, position;
+ int y;
+
+ if (s->prev && s->prev->face->underline_p)
+ {
+ /* We use the same underline style as the previous one. */
+ thickness = s->prev->underline_thickness;
+ position = s->prev->underline_position;
+ }
+ else
+ {
+ /* Get the underline thickness. Default is 1 pixel. */
+ if (s->font && s->font->underline_thickness > 0)
+ thickness = s->font->underline_thickness;
+ else
+ thickness = 1;
+ if (x_underline_at_descent_line)
+ position = (s->height - thickness) - (s->ybase - s->y);
+ else
+ {
+ /* Get the underline position. This is the recommended
+ vertical offset in pixels from the baseline to the
top of
+ the underline. This is a signed value according to
the
+ specs, and its default is
+
+ ROUND ((maximum_descent) / 2), with
+ ROUND (x) = floor (x + 0.5) */
+
+ if (x_use_underline_position_properties
+ && s->font && s->font->underline_position >= 0)
+ position = s->font->underline_position;
+ else if (s->font)
+ position = (s->font->descent + 1) / 2;
+ }
+ position = max (position, underline_minimum_offset);
+ }
+ /* Check the sanity of thickness and position. We should
+ avoid drawing underline out of the current line area. */
+ if (s->y + s->height <= s->ybase + position)
+ position = (s->height - 1) - (s->ybase - s->y);
+ if (s->y + s->height < s->ybase + position + thickness)
+ thickness = (s->y + s->height) - (s->ybase + position);
+ s->underline_thickness = thickness;
+ s->underline_position =position;
+ y = s->ybase + position;
+ if (s->face->underline_defaulted_p)
+ {
+ w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+ y, s->width, 1);
+ }
+ else
+ {
+ w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+ y, s->width, 1);
+ }
}
}
/* Draw overline. */
=== modified file 'src/xfaces.c'
--- a/src/xfaces.c 2012-06-09 16:44:44 +0000
+++ b/src/xfaces.c 2012-06-17 00:32:36 +0000
@@ -320,6 +320,7 @@
Lisp_Object Qnormal;
Lisp_Object Qbold;
+static Lisp_Object Qline, Qwave;
static Lisp_Object Qultra_light, Qextra_light, Qlight;
static Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold;
static Lisp_Object Qoblique, Qreverse_oblique, Qreverse_italic;
@@ -1894,7 +1895,8 @@
xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
|| SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
- || STRINGP (attrs[LFACE_UNDERLINE_INDEX]));
+ || STRINGP (attrs[LFACE_UNDERLINE_INDEX])
+ || CONSP (attrs[LFACE_UNDERLINE_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
|| SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
@@ -2525,7 +2527,8 @@
{
if (EQ (value, Qt)
|| NILP (value)
- || STRINGP (value))
+ || STRINGP (value)
+ || CONSP (value))
to[LFACE_UNDERLINE_INDEX] = value;
else
err = 1;
@@ -2948,15 +2951,54 @@
}
else if (EQ (attr, QCunderline))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
- if ((SYMBOLP (value)
- && !EQ (value, Qt)
- && !EQ (value, Qnil))
- /* Underline color. */
- || (STRINGP (value)
- && SCHARS (value) == 0))
- signal_error ("Invalid face underline", value);
-
+ int valid_p = 0;
+
+ if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
+ valid_p = 1;
+ else if (NILP (value) || EQ (value, Qt))
+ valid_p = 1;
+ else if (STRINGP (value) && SCHARS (value) > 0)
+ valid_p = 1;
+ else if (CONSP (value))
+ {
+ Lisp_Object key, val, list;
+
+ list = value;
+ valid_p = 1;
+
+ while (!NILP (CAR_SAFE(list)))
+ {
+ key = CAR_SAFE (list);
+ list = CDR_SAFE (list);
+ val = CAR_SAFE (list);
+ list = CDR_SAFE (list);
+
+ if(NILP (key) || NILP (val))
+ {
+ valid_p = 0;
+ break;
+ }
+
+ else if (EQ (key, QCcolor)
+ && !(EQ (val, Qforeground_color)
+ || (STRINGP (val) && SCHARS (val) > 0)))
+ {
+ valid_p = 0;
+ break;
+ }
+
+ else if (EQ (key, QCstyle)
+ && !(EQ (val, Qline) || EQ (val, Qwave)))
+ {
+ valid_p = 0;
+ break;
+ }
+ }
+ }
+
+ if (!valid_p)
+ signal_error ("Invalid face underline", value);
+
old_value = LFACE_UNDERLINE (lface);
LFACE_UNDERLINE (lface) = value;
}
@@ -5576,7 +5618,7 @@
#ifdef HAVE_WINDOW_SYSTEM
struct face *default_face;
struct frame *f;
- Lisp_Object stipple, overline, strike_through, box;
+ Lisp_Object stipple, underline, overline, strike_through, box;
xassert (FRAME_WINDOW_P (cache->f));
@@ -5709,29 +5751,76 @@
/* Text underline, overline, strike-through. */
- if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt))
+ underline = attrs[LFACE_UNDERLINE_INDEX];
+ if (EQ (underline, Qt))
{
/* Use default color (same as foreground color). */
face->underline_p = 1;
+ face->underline_type = FACE_UNDER_LINE;
face->underline_defaulted_p = 1;
face->underline_color = 0;
}
- else if (STRINGP (attrs[LFACE_UNDERLINE_INDEX]))
+ else if (STRINGP (underline))
{
/* Use specified color. */
face->underline_p = 1;
+ face->underline_type = FACE_UNDER_LINE;
face->underline_defaulted_p = 0;
face->underline_color
- = load_color (f, face, attrs[LFACE_UNDERLINE_INDEX],
+ = load_color (f, face, underline,
LFACE_UNDERLINE_INDEX);
}
- else if (NILP (attrs[LFACE_UNDERLINE_INDEX]))
+ else if (NILP (underline))
{
face->underline_p = 0;
face->underline_defaulted_p = 0;
face->underline_color = 0;
}
-
+ else if (CONSP (underline))
+ {
+ /* `(:color COLOR :style STYLE)'.
+ STYLE being one of `line' or `wave'. */
+ face->underline_p = 1;
+ face->underline_color = 0;
+ face->underline_defaulted_p = 1;
+ face->underline_type = FACE_UNDER_LINE;
+
+ while (CONSP (underline))
+ {
+ Lisp_Object keyword, value;
+
+ keyword = XCAR (underline);
+ underline = XCDR (underline);
+
+ if (!CONSP (underline))
+ break;
+ value = XCAR (underline);
+ underline = XCDR (underline);
+
+ if (EQ (keyword, QCcolor))
+ {
+ if (EQ (value, Qforeground_color))
+ {
+ face->underline_defaulted_p = 1;
+ face->underline_color = 0;
+ }
+ else if (STRINGP (value))
+ {
+ face->underline_defaulted_p = 0;
+ face->underline_color = load_color (f, face, value,
+ LFACE_UNDERLINE_INDEX);
+ }
+ }
+ else if (EQ (keyword, QCstyle))
+ {
+ if (EQ (value, Qline))
+ face->underline_type = FACE_UNDER_LINE;
+ else if (EQ (value, Qwave))
+ face->underline_type = FACE_UNDER_WAVE;
+ }
+ }
+ }
+
overline = attrs[LFACE_OVERLINE_INDEX];
if (STRINGP (overline))
{
@@ -6476,6 +6565,8 @@
DEFSYM (QCcolor, ":color");
DEFSYM (QCline_width, ":line-width");
DEFSYM (QCstyle, ":style");
+ DEFSYM (Qline, "line");
+ DEFSYM (Qwave, "wave");
DEFSYM (Qreleased_button, "released-button");
DEFSYM (Qpressed_button, "pressed-button");
DEFSYM (Qnormal, "normal");
=== modified file 'src/xterm.c'
--- a/src/xterm.c 2012-05-31 06:51:43 +0000
+++ b/src/xterm.c 2012-06-17 00:32:36 +0000
@@ -2663,6 +2663,65 @@
s->background_filled_p = 1;
}
+/*
+ Draw a wavy line under S. The wave fills wave_height pixels from y0.
+
+ x0 wave_length = 2
+ --
+ y0 * * * * *
+ |* * * * * * * * *
+ wave_height = 3 | * * * *
+
+*/
+
+static void
+x_draw_underwave (struct glyph_string *s)
+{
+ int wave_height = 2, wave_length = 3;
+ int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
+ XRectangle wave_clip, string_clip, final_clip;
+
+ dx = wave_length;
+ dy = wave_height - 1;
+ x0 = s->x;
+ y0 = s->ybase + 1;
+ width = s->width;
+ xmax = x0 + width;
+
+ /* Find and set clipping rectangle */
+
+ wave_clip = (XRectangle){ x0, y0, width, wave_height };
+ get_glyph_string_clip_rect (s, &string_clip);
+
+ if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
+ return;
+
+ XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted);
+
+ /* Draw the waves */
+
+ x1 = x0 - (x0 % dx);
+ x2 = x1 + dx;
+ odd = (x1/dx) % 2;
+ y1 = y2 = y0;
+
+ if (odd)
+ y1 += dy;
+ else
+ y2 += dy;
+
+ while (x1 <= xmax)
+ {
+ XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2);
+ x1 = x2, y1 = y2;
+ x2 += dx, y2 = y0 + odd*dy;
+ odd = !odd;
+ }
+
+ /* Restore previous clipping rectangle(s) */
+ XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips,
Unsorted);
+}
+
/* Draw glyph string S. */
@@ -2765,68 +2824,83 @@
{
/* Draw underline. */
if (s->face->underline_p)
- {
- unsigned long thickness, position;
- int y;
-
- if (s->prev && s->prev->face->underline_p)
- {
- /* We use the same underline style as the previous one. */
- thickness = s->prev->underline_thickness;
- position = s->prev->underline_position;
- }
- else
- {
- /* Get the underline thickness. Default is 1 pixel. */
- if (s->font && s->font->underline_thickness > 0)
- thickness = s->font->underline_thickness;
- else
- thickness = 1;
- if (x_underline_at_descent_line)
- position = (s->height - thickness) - (s->ybase - s->y);
- else
- {
- /* Get the underline position. This is the recommended
- vertical offset in pixels from the baseline to the top of
- the underline. This is a signed value according to the
- specs, and its default is
-
- ROUND ((maximum descent) / 2), with
- ROUND(x) = floor (x + 0.5) */
-
- if (x_use_underline_position_properties
- && s->font && s->font->underline_position >= 0)
- position = s->font->underline_position;
- else if (s->font)
- position = (s->font->descent + 1) / 2;
- else
- position = underline_minimum_offset;
- }
- position = max (position, underline_minimum_offset);
- }
- /* Check the sanity of thickness and position. We should
- avoid drawing underline out of the current line area. */
- if (s->y + s->height <= s->ybase + position)
- position = (s->height - 1) - (s->ybase - s->y);
- if (s->y + s->height < s->ybase + position + thickness)
- thickness = (s->y + s->height) - (s->ybase + position);
- s->underline_thickness = thickness;
- s->underline_position = position;
- y = s->ybase + position;
- if (s->face->underline_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc,
- s->x, y, s->width, thickness);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->underline_color);
- XFillRectangle (s->display, s->window, s->gc,
- s->x, y, s->width, thickness);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
+ {
+ if (s->face->underline_type == FACE_UNDER_WAVE)
+ {
+ if (s->face->underline_defaulted_p)
+ x_draw_underwave (s);
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+ XSetForeground (s->display, s->gc, s->face->underline_color);
+ x_draw_underwave (s);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+ else if (s->face->underline_type == FACE_UNDER_LINE)
+ {
+ unsigned long thickness, position;
+ int y;
+
+ if (s->prev && s->prev->face->underline_p)
+ {
+ /* We use the same underline style as the previous one. */
+ thickness = s->prev->underline_thickness;
+ position = s->prev->underline_position;
+ }
+ else
+ {
+ /* Get the underline thickness. Default is 1 pixel. */
+ if (s->font && s->font->underline_thickness > 0)
+ thickness = s->font->underline_thickness;
+ else
+ thickness = 1;
+ if (x_underline_at_descent_line)
+ position = (s->height - thickness) - (s->ybase - s->y);
+ else
+ {
+ /* Get the underline position. This is the recommended
+ vertical offset in pixels from the baseline to the
top of
+ the underline. This is a signed value according to
the
+ specs, and its default is
+
+ ROUND ((maximum descent) / 2), with
+ ROUND(x) = floor (x + 0.5) */
+
+ if (x_use_underline_position_properties
+ && s->font && s->font->underline_position >= 0)
+ position = s->font->underline_position;
+ else if (s->font)
+ position = (s->font->descent + 1) / 2;
+ else
+ position = underline_minimum_offset;
+ }
+ position = max (position, underline_minimum_offset);
+ }
+ /* Check the sanity of thickness and position. We should
+ avoid drawing underline out of the current line area. */
+ if (s->y + s->height <= s->ybase + position)
+ position = (s->height - 1) - (s->ybase - s->y);
+ if (s->y + s->height < s->ybase + position + thickness)
+ thickness = (s->y + s->height) - (s->ybase + position);
+ s->underline_thickness = thickness;
+ s->underline_position = position;
+ y = s->ybase + position;
+ if (s->face->underline_defaulted_p)
+ XFillRectangle (s->display, s->window, s->gc,
+ s->x, y, s->width, thickness);
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+ XSetForeground (s->display, s->gc, s->face->underline_color);
+ XFillRectangle (s->display, s->window, s->gc,
+ s->x, y, s->width, thickness);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+ }
/* Draw overline. */
if (s->face->overline_p)
{
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] /srv/bzr/emacs/trunk r108632: Merge implmentation of wave-style underline face attribute (debbugs.gnu.org/10736).,
Alp Aker <=