diff options
| author | Alp Aker | 2012-06-16 20:32:36 -0400 |
|---|---|---|
| committer | Alp Aker | 2012-06-16 20:32:36 -0400 |
| commit | 9b0e3ebaef5aed8097965b14c97a0579763be7fd (patch) | |
| tree | eeabc5495c58289454d9c53c9dd409377ec72cf3 /src | |
| parent | 40d8bcb854203237c6ad8327bc1fc0644f8734ec (diff) | |
| download | emacs-9b0e3ebaef5aed8097965b14c97a0579763be7fd.tar.gz emacs-9b0e3ebaef5aed8097965b14c97a0579763be7fd.zip | |
Implement wave-style variant of underlining.
* doc/lispref/display.texi: Document new face attribute.
* lisp/cus-face.el (custom-face-attributes): Add wave-style underline
attribute.
* lisp/faces.el (set-face-attribute): Update docstring.
* src/dispextern.h (face_underline_type): New enum.
(face): Add field for underline type.
* src/nsterm.m (ns_draw_underwave): New function.
(ns_draw_text_decoration): Use it.
* src/w32term.c (w32_restore_glyph_string_clip, w32_draw_underwave):
New functions.
(x_draw_glyph_string): Use them.
* src/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.
* src/xterm.c (x_draw_underwave): New function.
(x_draw_glyph_string): Use it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 17 | ||||
| -rw-r--r-- | src/dispextern.h | 10 | ||||
| -rw-r--r-- | src/nsterm.m | 158 | ||||
| -rw-r--r-- | src/w32term.c | 196 | ||||
| -rw-r--r-- | src/xfaces.c | 125 | ||||
| -rw-r--r-- | src/xterm.c | 196 |
6 files changed, 531 insertions, 171 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 321c3b9c62f..d392dd522b3 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,20 @@ | |||
| 1 | 2012-06-16 Aurelien Aptel <aurelien.aptel@gmail.com> | ||
| 2 | |||
| 3 | Implement wave-style variant of underlining. | ||
| 4 | * dispextern.h (face_underline_type): New enum. | ||
| 5 | (face): Add field for underline type. | ||
| 6 | * nsterm.m (ns_draw_underwave): New function. | ||
| 7 | (ns_draw_text_decoration): Use it. | ||
| 8 | * w32term.c (w32_restore_glyph_string_clip, w32_draw_underwave): | ||
| 9 | New functions. | ||
| 10 | (x_draw_glyph_string): Use them. | ||
| 11 | * xfaces.c (Qline, Qwave): New Lisp objects. | ||
| 12 | (check_lface_attrs, merge_face_ref) | ||
| 13 | (Finternal_set_lisp_face_attribute, realize_x_face): Handle | ||
| 14 | wave-style underline face attributes. | ||
| 15 | * xterm.c (x_draw_underwave): New function. | ||
| 16 | (x_draw_glyph_string): Use it. | ||
| 17 | |||
| 1 | 2012-06-16 Juanma Barranquero <lekktu@gmail.com> | 18 | 2012-06-16 Juanma Barranquero <lekktu@gmail.com> |
| 2 | 19 | ||
| 3 | * makefile.w32-in ($(BLD)/emacs.$(O), $(BLD)/fringe.$(O)) | 20 | * makefile.w32-in ($(BLD)/emacs.$(O), $(BLD)/fringe.$(O)) |
diff --git a/src/dispextern.h b/src/dispextern.h index 6e070f3dbef..fc7bec97f7a 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1510,6 +1510,13 @@ enum face_box_type | |||
| 1510 | FACE_SUNKEN_BOX | 1510 | FACE_SUNKEN_BOX |
| 1511 | }; | 1511 | }; |
| 1512 | 1512 | ||
| 1513 | /* Underline type. */ | ||
| 1514 | |||
| 1515 | enum face_underline_type | ||
| 1516 | { | ||
| 1517 | FACE_UNDER_LINE, | ||
| 1518 | FACE_UNDER_WAVE | ||
| 1519 | }; | ||
| 1513 | 1520 | ||
| 1514 | /* Structure describing a realized face. | 1521 | /* Structure describing a realized face. |
| 1515 | 1522 | ||
| @@ -1585,6 +1592,9 @@ struct face | |||
| 1585 | drawing shadows. */ | 1592 | drawing shadows. */ |
| 1586 | unsigned use_box_color_for_shadows_p : 1; | 1593 | unsigned use_box_color_for_shadows_p : 1; |
| 1587 | 1594 | ||
| 1595 | /* Style of underlining. */ | ||
| 1596 | enum face_underline_type underline_type; | ||
| 1597 | |||
| 1588 | /* Non-zero if text in this face should be underlined, overlined, | 1598 | /* Non-zero if text in this face should be underlined, overlined, |
| 1589 | strike-through or have a box drawn around it. */ | 1599 | strike-through or have a box drawn around it. */ |
| 1590 | unsigned underline_p : 1; | 1600 | unsigned underline_p : 1; |
diff --git a/src/nsterm.m b/src/nsterm.m index 8bd2bb283b2..48057302090 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -2595,6 +2595,60 @@ ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr) | |||
| 2595 | return n; | 2595 | return n; |
| 2596 | } | 2596 | } |
| 2597 | 2597 | ||
| 2598 | /* -------------------------------------------------------------------- | ||
| 2599 | Draw a wavy line under glyph string s. The wave fills wave_height | ||
| 2600 | pixels from y. | ||
| 2601 | |||
| 2602 | x wave_length = 3 | ||
| 2603 | -- | ||
| 2604 | y * * * * * | ||
| 2605 | |* * * * * * * * * | ||
| 2606 | wave_height = 3 | * * * * | ||
| 2607 | --------------------------------------------------------------------- */ | ||
| 2608 | |||
| 2609 | static void | ||
| 2610 | ns_draw_underwave (struct glyph_string *s, CGFloat width, CGFloat x) | ||
| 2611 | { | ||
| 2612 | int wave_height = 3, wave_length = 3; | ||
| 2613 | int y, dx, dy, odd, xmax; | ||
| 2614 | NSPoint a, b; | ||
| 2615 | NSRect waveClip; | ||
| 2616 | |||
| 2617 | dx = wave_length; | ||
| 2618 | dy = wave_height - 1; | ||
| 2619 | y = s->ybase + 1; | ||
| 2620 | xmax = x + width; | ||
| 2621 | |||
| 2622 | /* Find and set clipping rectangle */ | ||
| 2623 | waveClip = NSMakeRect (x, y, width, wave_height); | ||
| 2624 | [[NSGraphicsContext currentContext] saveGraphicsState]; | ||
| 2625 | NSRectClip (waveClip); | ||
| 2626 | |||
| 2627 | /* Draw the waves */ | ||
| 2628 | a.x = x - ((int)(x) % dx); | ||
| 2629 | b.x = a.x + dx; | ||
| 2630 | odd = (int)(a.x/dx) % 2; | ||
| 2631 | a.y = b.y = y; | ||
| 2632 | |||
| 2633 | if (odd) | ||
| 2634 | a.y += dy; | ||
| 2635 | else | ||
| 2636 | b.y += dy; | ||
| 2637 | |||
| 2638 | while (a.x <= xmax) | ||
| 2639 | { | ||
| 2640 | [NSBezierPath strokeLineFromPoint:a toPoint:b]; | ||
| 2641 | a.x = b.x, a.y = b.y; | ||
| 2642 | b.x += dx, b.y = y + odd*dy; | ||
| 2643 | odd = !odd; | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | /* Restore previous clipping rectangle(s) */ | ||
| 2647 | [[NSGraphicsContext currentContext] restoreGraphicsState]; | ||
| 2648 | } | ||
| 2649 | |||
| 2650 | |||
| 2651 | |||
| 2598 | void | 2652 | void |
| 2599 | ns_draw_text_decoration (struct glyph_string *s, struct face *face, | 2653 | ns_draw_text_decoration (struct glyph_string *s, struct face *face, |
| 2600 | NSColor *defaultCol, CGFloat width, CGFloat x) | 2654 | NSColor *defaultCol, CGFloat width, CGFloat x) |
| @@ -2608,63 +2662,75 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, | |||
| 2608 | /* Do underline. */ | 2662 | /* Do underline. */ |
| 2609 | if (face->underline_p) | 2663 | if (face->underline_p) |
| 2610 | { | 2664 | { |
| 2611 | NSRect r; | 2665 | if (s->face->underline_type == FACE_UNDER_WAVE) |
| 2612 | unsigned long thickness, position; | ||
| 2613 | |||
| 2614 | /* If the prev was underlined, match its appearance. */ | ||
| 2615 | if (s->prev && s->prev->face->underline_p | ||
| 2616 | && s->prev->underline_thickness > 0) | ||
| 2617 | { | 2666 | { |
| 2618 | thickness = s->prev->underline_thickness; | 2667 | if (face->underline_defaulted_p) |
| 2619 | position = s->prev->underline_position; | 2668 | [defaultCol set]; |
| 2669 | else | ||
| 2670 | [ns_lookup_indexed_color (face->underline_color, s->f) set]; | ||
| 2671 | |||
| 2672 | ns_draw_underwave (s, width, x); | ||
| 2620 | } | 2673 | } |
| 2621 | else | 2674 | else if (s->face->underline_type == FACE_UNDER_LINE) |
| 2622 | { | 2675 | { |
| 2623 | struct font *font; | ||
| 2624 | unsigned long descent; | ||
| 2625 | |||
| 2626 | font=s->font; | ||
| 2627 | descent = s->y + s->height - s->ybase; | ||
| 2628 | |||
| 2629 | /* Use underline thickness of font, defaulting to 1. */ | ||
| 2630 | thickness = (font && font->underline_thickness > 0) | ||
| 2631 | ? font->underline_thickness : 1; | ||
| 2632 | |||
| 2633 | /* Determine the offset of underlining from the baseline. */ | ||
| 2634 | if (x_underline_at_descent_line) | ||
| 2635 | position = descent - thickness; | ||
| 2636 | else if (x_use_underline_position_properties | ||
| 2637 | && font && font->underline_position >= 0) | ||
| 2638 | position = font->underline_position; | ||
| 2639 | else if (font) | ||
| 2640 | position = lround (font->descent / 2); | ||
| 2641 | else | ||
| 2642 | position = underline_minimum_offset; | ||
| 2643 | 2676 | ||
| 2644 | position = max (position, underline_minimum_offset); | 2677 | NSRect r; |
| 2678 | unsigned long thickness, position; | ||
| 2645 | 2679 | ||
| 2646 | /* Ensure underlining is not cropped. */ | 2680 | /* If the prev was underlined, match its appearance. */ |
| 2647 | if (descent <= position) | 2681 | if (s->prev && s->prev->face->underline_p |
| 2682 | && s->prev->underline_thickness > 0) | ||
| 2648 | { | 2683 | { |
| 2649 | position = descent - 1; | 2684 | thickness = s->prev->underline_thickness; |
| 2650 | thickness = 1; | 2685 | position = s->prev->underline_position; |
| 2651 | } | 2686 | } |
| 2652 | else if (descent < position + thickness) | 2687 | else |
| 2653 | thickness = 1; | 2688 | { |
| 2654 | } | 2689 | struct font *font; |
| 2690 | unsigned long descent; | ||
| 2691 | |||
| 2692 | font=s->font; | ||
| 2693 | descent = s->y + s->height - s->ybase; | ||
| 2694 | |||
| 2695 | /* Use underline thickness of font, defaulting to 1. */ | ||
| 2696 | thickness = (font && font->underline_thickness > 0) | ||
| 2697 | ? font->underline_thickness : 1; | ||
| 2698 | |||
| 2699 | /* Determine the offset of underlining from the baseline. */ | ||
| 2700 | if (x_underline_at_descent_line) | ||
| 2701 | position = descent - thickness; | ||
| 2702 | else if (x_use_underline_position_properties | ||
| 2703 | && font && font->underline_position >= 0) | ||
| 2704 | position = font->underline_position; | ||
| 2705 | else if (font) | ||
| 2706 | position = lround (font->descent / 2); | ||
| 2707 | else | ||
| 2708 | position = underline_minimum_offset; | ||
| 2655 | 2709 | ||
| 2656 | s->underline_thickness = thickness; | 2710 | position = max (position, underline_minimum_offset); |
| 2657 | s->underline_position = position; | ||
| 2658 | 2711 | ||
| 2659 | r = NSMakeRect (x, s->ybase + position, width, thickness); | 2712 | /* Ensure underlining is not cropped. */ |
| 2713 | if (descent <= position) | ||
| 2714 | { | ||
| 2715 | position = descent - 1; | ||
| 2716 | thickness = 1; | ||
| 2717 | } | ||
| 2718 | else if (descent < position + thickness) | ||
| 2719 | thickness = 1; | ||
| 2720 | } | ||
| 2660 | 2721 | ||
| 2661 | if (face->underline_defaulted_p) | 2722 | s->underline_thickness = thickness; |
| 2662 | [defaultCol set]; | 2723 | s->underline_position = position; |
| 2663 | else | 2724 | |
| 2664 | [ns_lookup_indexed_color (face->underline_color, s->f) set]; | 2725 | r = NSMakeRect (x, s->ybase + position, width, thickness); |
| 2665 | NSRectFill (r); | ||
| 2666 | } | ||
| 2667 | 2726 | ||
| 2727 | if (face->underline_defaulted_p) | ||
| 2728 | [defaultCol set]; | ||
| 2729 | else | ||
| 2730 | [ns_lookup_indexed_color (face->underline_color, s->f) set]; | ||
| 2731 | NSRectFill (r); | ||
| 2732 | } | ||
| 2733 | } | ||
| 2668 | /* Do overline. We follow other terms in using a thickness of 1 | 2734 | /* Do overline. We follow other terms in using a thickness of 1 |
| 2669 | and ignoring overline_margin. */ | 2735 | and ignoring overline_margin. */ |
| 2670 | if (face->overline_p) | 2736 | if (face->overline_p) |
diff --git a/src/w32term.c b/src/w32term.c index 38120b77ac9..6a4b3ca4afb 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -313,6 +313,94 @@ w32_set_clip_rectangle (HDC hdc, RECT *rect) | |||
| 313 | SelectClipRgn (hdc, NULL); | 313 | SelectClipRgn (hdc, NULL); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | /* Restore clipping rectangle in S */ | ||
| 317 | static void | ||
| 318 | w32_restore_glyph_string_clip (struct glyph_string *s) | ||
| 319 | { | ||
| 320 | RECT *r = s->clip; | ||
| 321 | int n = s->num_clips; | ||
| 322 | |||
| 323 | if (n == 1) | ||
| 324 | w32_set_clip_rectangle (s->hdc, r); | ||
| 325 | else if (n > 1) | ||
| 326 | { | ||
| 327 | HRGN clip1 = CreateRectRgnIndirect (r); | ||
| 328 | HRGN clip2 = CreateRectRgnIndirect (r + 1); | ||
| 329 | if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR) | ||
| 330 | SelectClipRgn (s->hdc, clip1); | ||
| 331 | DeleteObject (clip1); | ||
| 332 | DeleteObject (clip2); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | /* | ||
| 337 | Draw a wavy line under S. The wave fills wave_height pixels from y0. | ||
| 338 | |||
| 339 | x0 wave_length = 2 | ||
| 340 | -- | ||
| 341 | y0 * * * * * | ||
| 342 | |* * * * * * * * * | ||
| 343 | wave_height = 3 | * * * * | ||
| 344 | |||
| 345 | */ | ||
| 346 | |||
| 347 | void | ||
| 348 | w32_draw_underwave (struct glyph_string *s, COLORREF color) | ||
| 349 | { | ||
| 350 | int wave_height = 2, wave_length = 3; | ||
| 351 | int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax; | ||
| 352 | XRectangle wave_clip, string_clip, final_clip; | ||
| 353 | RECT w32_final_clip, w32_string_clip; | ||
| 354 | HPEN hp, oldhp; | ||
| 355 | |||
| 356 | dx = wave_length; | ||
| 357 | dy = wave_height - 1; | ||
| 358 | x0 = s->x; | ||
| 359 | y0 = s->ybase + 1; | ||
| 360 | width = s->width; | ||
| 361 | xmax = x0 + width; | ||
| 362 | |||
| 363 | /* Find and set clipping rectangle */ | ||
| 364 | |||
| 365 | wave_clip = (XRectangle){ x0, y0, width, wave_height }; | ||
| 366 | get_glyph_string_clip_rect (s, &w32_string_clip); | ||
| 367 | CONVERT_TO_XRECT (string_clip, w32_string_clip); | ||
| 368 | |||
| 369 | if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip)) | ||
| 370 | return; | ||
| 371 | |||
| 372 | hp = CreatePen (PS_SOLID, 0, color); | ||
| 373 | oldhp = SelectObject (s->hdc, hp); | ||
| 374 | CONVERT_FROM_XRECT (final_clip, w32_final_clip); | ||
| 375 | w32_set_clip_rectangle (s->hdc, &w32_final_clip); | ||
| 376 | |||
| 377 | /* Draw the waves */ | ||
| 378 | |||
| 379 | x1 = x0 - (x0 % dx); | ||
| 380 | x2 = x1 + dx; | ||
| 381 | odd = (x1/dx) % 2; | ||
| 382 | y1 = y2 = y0; | ||
| 383 | |||
| 384 | if (odd) | ||
| 385 | y1 += dy; | ||
| 386 | else | ||
| 387 | y2 += dy; | ||
| 388 | |||
| 389 | MoveToEx (s->hdc, x1, y1, NULL); | ||
| 390 | |||
| 391 | while (x1 <= xmax) | ||
| 392 | { | ||
| 393 | LineTo (s->hdc, x2, y2); | ||
| 394 | x1 = x2, y1 = y2; | ||
| 395 | x2 += dx, y2 = y0 + odd*dy; | ||
| 396 | odd = !odd; | ||
| 397 | } | ||
| 398 | |||
| 399 | /* Restore previous pen and clipping rectangle(s) */ | ||
| 400 | w32_restore_glyph_string_clip (s); | ||
| 401 | SelectObject (s->hdc, oldhp); | ||
| 402 | DeleteObject (hp); | ||
| 403 | } | ||
| 316 | 404 | ||
| 317 | /* Draw a hollow rectangle at the specified position. */ | 405 | /* Draw a hollow rectangle at the specified position. */ |
| 318 | void | 406 | void |
| @@ -2347,60 +2435,74 @@ x_draw_glyph_string (struct glyph_string *s) | |||
| 2347 | /* Draw underline. */ | 2435 | /* Draw underline. */ |
| 2348 | if (s->face->underline_p) | 2436 | if (s->face->underline_p) |
| 2349 | { | 2437 | { |
| 2350 | unsigned long thickness, position; | 2438 | if (s->face->underline_type == FACE_UNDER_WAVE) |
| 2351 | int y; | ||
| 2352 | |||
| 2353 | if (s->prev && s->prev->face->underline_p) | ||
| 2354 | { | 2439 | { |
| 2355 | /* We use the same underline style as the previous one. */ | 2440 | COLORREF color; |
| 2356 | thickness = s->prev->underline_thickness; | 2441 | |
| 2357 | position = s->prev->underline_position; | 2442 | if (s->face->underline_defaulted_p) |
| 2443 | color = s->gc->foreground; | ||
| 2444 | else | ||
| 2445 | color = s->face->underline_color; | ||
| 2446 | |||
| 2447 | w32_draw_underwave (s, color); | ||
| 2358 | } | 2448 | } |
| 2359 | else | 2449 | else if (s->face->underline_type == FACE_UNDER_LINE) |
| 2360 | { | 2450 | { |
| 2361 | /* Get the underline thickness. Default is 1 pixel. */ | 2451 | unsigned long thickness, position; |
| 2362 | if (s->font && s->font->underline_thickness > 0) | 2452 | int y; |
| 2363 | thickness = s->font->underline_thickness; | 2453 | |
| 2454 | if (s->prev && s->prev->face->underline_p) | ||
| 2455 | { | ||
| 2456 | /* We use the same underline style as the previous one. */ | ||
| 2457 | thickness = s->prev->underline_thickness; | ||
| 2458 | position = s->prev->underline_position; | ||
| 2459 | } | ||
| 2364 | else | 2460 | else |
| 2365 | thickness = 1; | 2461 | { |
| 2366 | if (x_underline_at_descent_line) | 2462 | /* Get the underline thickness. Default is 1 pixel. */ |
| 2367 | position = (s->height - thickness) - (s->ybase - s->y); | 2463 | if (s->font && s->font->underline_thickness > 0) |
| 2464 | thickness = s->font->underline_thickness; | ||
| 2465 | else | ||
| 2466 | thickness = 1; | ||
| 2467 | if (x_underline_at_descent_line) | ||
| 2468 | position = (s->height - thickness) - (s->ybase - s->y); | ||
| 2469 | else | ||
| 2470 | { | ||
| 2471 | /* Get the underline position. This is the recommended | ||
| 2472 | vertical offset in pixels from the baseline to the top of | ||
| 2473 | the underline. This is a signed value according to the | ||
| 2474 | specs, and its default is | ||
| 2475 | |||
| 2476 | ROUND ((maximum_descent) / 2), with | ||
| 2477 | ROUND (x) = floor (x + 0.5) */ | ||
| 2478 | |||
| 2479 | if (x_use_underline_position_properties | ||
| 2480 | && s->font && s->font->underline_position >= 0) | ||
| 2481 | position = s->font->underline_position; | ||
| 2482 | else if (s->font) | ||
| 2483 | position = (s->font->descent + 1) / 2; | ||
| 2484 | } | ||
| 2485 | position = max (position, underline_minimum_offset); | ||
| 2486 | } | ||
| 2487 | /* Check the sanity of thickness and position. We should | ||
| 2488 | avoid drawing underline out of the current line area. */ | ||
| 2489 | if (s->y + s->height <= s->ybase + position) | ||
| 2490 | position = (s->height - 1) - (s->ybase - s->y); | ||
| 2491 | if (s->y + s->height < s->ybase + position + thickness) | ||
| 2492 | thickness = (s->y + s->height) - (s->ybase + position); | ||
| 2493 | s->underline_thickness = thickness; | ||
| 2494 | s->underline_position =position; | ||
| 2495 | y = s->ybase + position; | ||
| 2496 | if (s->face->underline_defaulted_p) | ||
| 2497 | { | ||
| 2498 | w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, | ||
| 2499 | y, s->width, 1); | ||
| 2500 | } | ||
| 2368 | else | 2501 | else |
| 2369 | { | 2502 | { |
| 2370 | /* Get the underline position. This is the recommended | 2503 | w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x, |
| 2371 | vertical offset in pixels from the baseline to the top of | 2504 | y, s->width, 1); |
| 2372 | the underline. This is a signed value according to the | ||
| 2373 | specs, and its default is | ||
| 2374 | |||
| 2375 | ROUND ((maximum_descent) / 2), with | ||
| 2376 | ROUND (x) = floor (x + 0.5) */ | ||
| 2377 | |||
| 2378 | if (x_use_underline_position_properties | ||
| 2379 | && s->font && s->font->underline_position >= 0) | ||
| 2380 | position = s->font->underline_position; | ||
| 2381 | else if (s->font) | ||
| 2382 | position = (s->font->descent + 1) / 2; | ||
| 2383 | } | 2505 | } |
| 2384 | position = max (position, underline_minimum_offset); | ||
| 2385 | } | ||
| 2386 | /* Check the sanity of thickness and position. We should | ||
| 2387 | avoid drawing underline out of the current line area. */ | ||
| 2388 | if (s->y + s->height <= s->ybase + position) | ||
| 2389 | position = (s->height - 1) - (s->ybase - s->y); | ||
| 2390 | if (s->y + s->height < s->ybase + position + thickness) | ||
| 2391 | thickness = (s->y + s->height) - (s->ybase + position); | ||
| 2392 | s->underline_thickness = thickness; | ||
| 2393 | s->underline_position =position; | ||
| 2394 | y = s->ybase + position; | ||
| 2395 | if (s->face->underline_defaulted_p) | ||
| 2396 | { | ||
| 2397 | w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, | ||
| 2398 | y, s->width, 1); | ||
| 2399 | } | ||
| 2400 | else | ||
| 2401 | { | ||
| 2402 | w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x, | ||
| 2403 | y, s->width, 1); | ||
| 2404 | } | 2506 | } |
| 2405 | } | 2507 | } |
| 2406 | /* Draw overline. */ | 2508 | /* Draw overline. */ |
diff --git a/src/xfaces.c b/src/xfaces.c index 772d2646291..32d1499b85a 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -320,6 +320,7 @@ static Lisp_Object QCfontset; | |||
| 320 | 320 | ||
| 321 | Lisp_Object Qnormal; | 321 | Lisp_Object Qnormal; |
| 322 | Lisp_Object Qbold; | 322 | Lisp_Object Qbold; |
| 323 | static Lisp_Object Qline, Qwave; | ||
| 323 | static Lisp_Object Qultra_light, Qextra_light, Qlight; | 324 | static Lisp_Object Qultra_light, Qextra_light, Qlight; |
| 324 | static Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold; | 325 | static Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold; |
| 325 | static Lisp_Object Qoblique, Qreverse_oblique, Qreverse_italic; | 326 | static Lisp_Object Qoblique, Qreverse_oblique, Qreverse_italic; |
| @@ -1894,7 +1895,8 @@ check_lface_attrs (Lisp_Object *attrs) | |||
| 1894 | xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) | 1895 | xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) |
| 1895 | || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX]) | 1896 | || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX]) |
| 1896 | || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX]) | 1897 | || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX]) |
| 1897 | || STRINGP (attrs[LFACE_UNDERLINE_INDEX])); | 1898 | || STRINGP (attrs[LFACE_UNDERLINE_INDEX]) |
| 1899 | || CONSP (attrs[LFACE_UNDERLINE_INDEX])); | ||
| 1898 | xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) | 1900 | xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) |
| 1899 | || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX]) | 1901 | || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX]) |
| 1900 | || SYMBOLP (attrs[LFACE_OVERLINE_INDEX]) | 1902 | || SYMBOLP (attrs[LFACE_OVERLINE_INDEX]) |
| @@ -2525,7 +2527,8 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to, | |||
| 2525 | { | 2527 | { |
| 2526 | if (EQ (value, Qt) | 2528 | if (EQ (value, Qt) |
| 2527 | || NILP (value) | 2529 | || NILP (value) |
| 2528 | || STRINGP (value)) | 2530 | || STRINGP (value) |
| 2531 | || CONSP (value)) | ||
| 2529 | to[LFACE_UNDERLINE_INDEX] = value; | 2532 | to[LFACE_UNDERLINE_INDEX] = value; |
| 2530 | else | 2533 | else |
| 2531 | err = 1; | 2534 | err = 1; |
| @@ -2948,15 +2951,54 @@ FRAME 0 means change the face on all frames, and change the default | |||
| 2948 | } | 2951 | } |
| 2949 | else if (EQ (attr, QCunderline)) | 2952 | else if (EQ (attr, QCunderline)) |
| 2950 | { | 2953 | { |
| 2951 | if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) | 2954 | int valid_p = 0; |
| 2952 | if ((SYMBOLP (value) | 2955 | |
| 2953 | && !EQ (value, Qt) | 2956 | if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value)) |
| 2954 | && !EQ (value, Qnil)) | 2957 | valid_p = 1; |
| 2955 | /* Underline color. */ | 2958 | else if (NILP (value) || EQ (value, Qt)) |
| 2956 | || (STRINGP (value) | 2959 | valid_p = 1; |
| 2957 | && SCHARS (value) == 0)) | 2960 | else if (STRINGP (value) && SCHARS (value) > 0) |
| 2958 | signal_error ("Invalid face underline", value); | 2961 | valid_p = 1; |
| 2959 | 2962 | else if (CONSP (value)) | |
| 2963 | { | ||
| 2964 | Lisp_Object key, val, list; | ||
| 2965 | |||
| 2966 | list = value; | ||
| 2967 | valid_p = 1; | ||
| 2968 | |||
| 2969 | while (!NILP (CAR_SAFE(list))) | ||
| 2970 | { | ||
| 2971 | key = CAR_SAFE (list); | ||
| 2972 | list = CDR_SAFE (list); | ||
| 2973 | val = CAR_SAFE (list); | ||
| 2974 | list = CDR_SAFE (list); | ||
| 2975 | |||
| 2976 | if(NILP (key) || NILP (val)) | ||
| 2977 | { | ||
| 2978 | valid_p = 0; | ||
| 2979 | break; | ||
| 2980 | } | ||
| 2981 | |||
| 2982 | else if (EQ (key, QCcolor) | ||
| 2983 | && !(EQ (val, Qforeground_color) | ||
| 2984 | || (STRINGP (val) && SCHARS (val) > 0))) | ||
| 2985 | { | ||
| 2986 | valid_p = 0; | ||
| 2987 | break; | ||
| 2988 | } | ||
| 2989 | |||
| 2990 | else if (EQ (key, QCstyle) | ||
| 2991 | && !(EQ (val, Qline) || EQ (val, Qwave))) | ||
| 2992 | { | ||
| 2993 | valid_p = 0; | ||
| 2994 | break; | ||
| 2995 | } | ||
| 2996 | } | ||
| 2997 | } | ||
| 2998 | |||
| 2999 | if (!valid_p) | ||
| 3000 | signal_error ("Invalid face underline", value); | ||
| 3001 | |||
| 2960 | old_value = LFACE_UNDERLINE (lface); | 3002 | old_value = LFACE_UNDERLINE (lface); |
| 2961 | LFACE_UNDERLINE (lface) = value; | 3003 | LFACE_UNDERLINE (lface) = value; |
| 2962 | } | 3004 | } |
| @@ -5576,7 +5618,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object *attrs) | |||
| 5576 | #ifdef HAVE_WINDOW_SYSTEM | 5618 | #ifdef HAVE_WINDOW_SYSTEM |
| 5577 | struct face *default_face; | 5619 | struct face *default_face; |
| 5578 | struct frame *f; | 5620 | struct frame *f; |
| 5579 | Lisp_Object stipple, overline, strike_through, box; | 5621 | Lisp_Object stipple, underline, overline, strike_through, box; |
| 5580 | 5622 | ||
| 5581 | xassert (FRAME_WINDOW_P (cache->f)); | 5623 | xassert (FRAME_WINDOW_P (cache->f)); |
| 5582 | 5624 | ||
| @@ -5709,29 +5751,76 @@ realize_x_face (struct face_cache *cache, Lisp_Object *attrs) | |||
| 5709 | 5751 | ||
| 5710 | /* Text underline, overline, strike-through. */ | 5752 | /* Text underline, overline, strike-through. */ |
| 5711 | 5753 | ||
| 5712 | if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt)) | 5754 | underline = attrs[LFACE_UNDERLINE_INDEX]; |
| 5755 | if (EQ (underline, Qt)) | ||
| 5713 | { | 5756 | { |
| 5714 | /* Use default color (same as foreground color). */ | 5757 | /* Use default color (same as foreground color). */ |
| 5715 | face->underline_p = 1; | 5758 | face->underline_p = 1; |
| 5759 | face->underline_type = FACE_UNDER_LINE; | ||
| 5716 | face->underline_defaulted_p = 1; | 5760 | face->underline_defaulted_p = 1; |
| 5717 | face->underline_color = 0; | 5761 | face->underline_color = 0; |
| 5718 | } | 5762 | } |
| 5719 | else if (STRINGP (attrs[LFACE_UNDERLINE_INDEX])) | 5763 | else if (STRINGP (underline)) |
| 5720 | { | 5764 | { |
| 5721 | /* Use specified color. */ | 5765 | /* Use specified color. */ |
| 5722 | face->underline_p = 1; | 5766 | face->underline_p = 1; |
| 5767 | face->underline_type = FACE_UNDER_LINE; | ||
| 5723 | face->underline_defaulted_p = 0; | 5768 | face->underline_defaulted_p = 0; |
| 5724 | face->underline_color | 5769 | face->underline_color |
| 5725 | = load_color (f, face, attrs[LFACE_UNDERLINE_INDEX], | 5770 | = load_color (f, face, underline, |
| 5726 | LFACE_UNDERLINE_INDEX); | 5771 | LFACE_UNDERLINE_INDEX); |
| 5727 | } | 5772 | } |
| 5728 | else if (NILP (attrs[LFACE_UNDERLINE_INDEX])) | 5773 | else if (NILP (underline)) |
| 5729 | { | 5774 | { |
| 5730 | face->underline_p = 0; | 5775 | face->underline_p = 0; |
| 5731 | face->underline_defaulted_p = 0; | 5776 | face->underline_defaulted_p = 0; |
| 5732 | face->underline_color = 0; | 5777 | face->underline_color = 0; |
| 5733 | } | 5778 | } |
| 5734 | 5779 | else if (CONSP (underline)) | |
| 5780 | { | ||
| 5781 | /* `(:color COLOR :style STYLE)'. | ||
| 5782 | STYLE being one of `line' or `wave'. */ | ||
| 5783 | face->underline_p = 1; | ||
| 5784 | face->underline_color = 0; | ||
| 5785 | face->underline_defaulted_p = 1; | ||
| 5786 | face->underline_type = FACE_UNDER_LINE; | ||
| 5787 | |||
| 5788 | while (CONSP (underline)) | ||
| 5789 | { | ||
| 5790 | Lisp_Object keyword, value; | ||
| 5791 | |||
| 5792 | keyword = XCAR (underline); | ||
| 5793 | underline = XCDR (underline); | ||
| 5794 | |||
| 5795 | if (!CONSP (underline)) | ||
| 5796 | break; | ||
| 5797 | value = XCAR (underline); | ||
| 5798 | underline = XCDR (underline); | ||
| 5799 | |||
| 5800 | if (EQ (keyword, QCcolor)) | ||
| 5801 | { | ||
| 5802 | if (EQ (value, Qforeground_color)) | ||
| 5803 | { | ||
| 5804 | face->underline_defaulted_p = 1; | ||
| 5805 | face->underline_color = 0; | ||
| 5806 | } | ||
| 5807 | else if (STRINGP (value)) | ||
| 5808 | { | ||
| 5809 | face->underline_defaulted_p = 0; | ||
| 5810 | face->underline_color = load_color (f, face, value, | ||
| 5811 | LFACE_UNDERLINE_INDEX); | ||
| 5812 | } | ||
| 5813 | } | ||
| 5814 | else if (EQ (keyword, QCstyle)) | ||
| 5815 | { | ||
| 5816 | if (EQ (value, Qline)) | ||
| 5817 | face->underline_type = FACE_UNDER_LINE; | ||
| 5818 | else if (EQ (value, Qwave)) | ||
| 5819 | face->underline_type = FACE_UNDER_WAVE; | ||
| 5820 | } | ||
| 5821 | } | ||
| 5822 | } | ||
| 5823 | |||
| 5735 | overline = attrs[LFACE_OVERLINE_INDEX]; | 5824 | overline = attrs[LFACE_OVERLINE_INDEX]; |
| 5736 | if (STRINGP (overline)) | 5825 | if (STRINGP (overline)) |
| 5737 | { | 5826 | { |
| @@ -6476,6 +6565,8 @@ syms_of_xfaces (void) | |||
| 6476 | DEFSYM (QCcolor, ":color"); | 6565 | DEFSYM (QCcolor, ":color"); |
| 6477 | DEFSYM (QCline_width, ":line-width"); | 6566 | DEFSYM (QCline_width, ":line-width"); |
| 6478 | DEFSYM (QCstyle, ":style"); | 6567 | DEFSYM (QCstyle, ":style"); |
| 6568 | DEFSYM (Qline, "line"); | ||
| 6569 | DEFSYM (Qwave, "wave"); | ||
| 6479 | DEFSYM (Qreleased_button, "released-button"); | 6570 | DEFSYM (Qreleased_button, "released-button"); |
| 6480 | DEFSYM (Qpressed_button, "pressed-button"); | 6571 | DEFSYM (Qpressed_button, "pressed-button"); |
| 6481 | DEFSYM (Qnormal, "normal"); | 6572 | DEFSYM (Qnormal, "normal"); |
diff --git a/src/xterm.c b/src/xterm.c index 3c7a7efdd71..914d195778f 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -2663,6 +2663,65 @@ x_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 2663 | s->background_filled_p = 1; | 2663 | s->background_filled_p = 1; |
| 2664 | } | 2664 | } |
| 2665 | 2665 | ||
| 2666 | /* | ||
| 2667 | Draw a wavy line under S. The wave fills wave_height pixels from y0. | ||
| 2668 | |||
| 2669 | x0 wave_length = 2 | ||
| 2670 | -- | ||
| 2671 | y0 * * * * * | ||
| 2672 | |* * * * * * * * * | ||
| 2673 | wave_height = 3 | * * * * | ||
| 2674 | |||
| 2675 | */ | ||
| 2676 | |||
| 2677 | static void | ||
| 2678 | x_draw_underwave (struct glyph_string *s) | ||
| 2679 | { | ||
| 2680 | int wave_height = 2, wave_length = 3; | ||
| 2681 | int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax; | ||
| 2682 | XRectangle wave_clip, string_clip, final_clip; | ||
| 2683 | |||
| 2684 | dx = wave_length; | ||
| 2685 | dy = wave_height - 1; | ||
| 2686 | x0 = s->x; | ||
| 2687 | y0 = s->ybase + 1; | ||
| 2688 | width = s->width; | ||
| 2689 | xmax = x0 + width; | ||
| 2690 | |||
| 2691 | /* Find and set clipping rectangle */ | ||
| 2692 | |||
| 2693 | wave_clip = (XRectangle){ x0, y0, width, wave_height }; | ||
| 2694 | get_glyph_string_clip_rect (s, &string_clip); | ||
| 2695 | |||
| 2696 | if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip)) | ||
| 2697 | return; | ||
| 2698 | |||
| 2699 | XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted); | ||
| 2700 | |||
| 2701 | /* Draw the waves */ | ||
| 2702 | |||
| 2703 | x1 = x0 - (x0 % dx); | ||
| 2704 | x2 = x1 + dx; | ||
| 2705 | odd = (x1/dx) % 2; | ||
| 2706 | y1 = y2 = y0; | ||
| 2707 | |||
| 2708 | if (odd) | ||
| 2709 | y1 += dy; | ||
| 2710 | else | ||
| 2711 | y2 += dy; | ||
| 2712 | |||
| 2713 | while (x1 <= xmax) | ||
| 2714 | { | ||
| 2715 | XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2); | ||
| 2716 | x1 = x2, y1 = y2; | ||
| 2717 | x2 += dx, y2 = y0 + odd*dy; | ||
| 2718 | odd = !odd; | ||
| 2719 | } | ||
| 2720 | |||
| 2721 | /* Restore previous clipping rectangle(s) */ | ||
| 2722 | XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted); | ||
| 2723 | } | ||
| 2724 | |||
| 2666 | 2725 | ||
| 2667 | /* Draw glyph string S. */ | 2726 | /* Draw glyph string S. */ |
| 2668 | 2727 | ||
| @@ -2765,68 +2824,83 @@ x_draw_glyph_string (struct glyph_string *s) | |||
| 2765 | { | 2824 | { |
| 2766 | /* Draw underline. */ | 2825 | /* Draw underline. */ |
| 2767 | if (s->face->underline_p) | 2826 | if (s->face->underline_p) |
| 2768 | { | 2827 | { |
| 2769 | unsigned long thickness, position; | 2828 | if (s->face->underline_type == FACE_UNDER_WAVE) |
| 2770 | int y; | 2829 | { |
| 2771 | 2830 | if (s->face->underline_defaulted_p) | |
| 2772 | if (s->prev && s->prev->face->underline_p) | 2831 | x_draw_underwave (s); |
| 2773 | { | 2832 | else |
| 2774 | /* We use the same underline style as the previous one. */ | 2833 | { |
| 2775 | thickness = s->prev->underline_thickness; | 2834 | XGCValues xgcv; |
| 2776 | position = s->prev->underline_position; | 2835 | XGetGCValues (s->display, s->gc, GCForeground, &xgcv); |
| 2777 | } | 2836 | XSetForeground (s->display, s->gc, s->face->underline_color); |
| 2778 | else | 2837 | x_draw_underwave (s); |
| 2779 | { | 2838 | XSetForeground (s->display, s->gc, xgcv.foreground); |
| 2780 | /* Get the underline thickness. Default is 1 pixel. */ | 2839 | } |
| 2781 | if (s->font && s->font->underline_thickness > 0) | 2840 | } |
| 2782 | thickness = s->font->underline_thickness; | 2841 | else if (s->face->underline_type == FACE_UNDER_LINE) |
| 2783 | else | 2842 | { |
| 2784 | thickness = 1; | 2843 | unsigned long thickness, position; |
| 2785 | if (x_underline_at_descent_line) | 2844 | int y; |
| 2786 | position = (s->height - thickness) - (s->ybase - s->y); | ||
| 2787 | else | ||
| 2788 | { | ||
| 2789 | /* Get the underline position. This is the recommended | ||
| 2790 | vertical offset in pixels from the baseline to the top of | ||
| 2791 | the underline. This is a signed value according to the | ||
| 2792 | specs, and its default is | ||
| 2793 | |||
| 2794 | ROUND ((maximum descent) / 2), with | ||
| 2795 | ROUND(x) = floor (x + 0.5) */ | ||
| 2796 | |||
| 2797 | if (x_use_underline_position_properties | ||
| 2798 | && s->font && s->font->underline_position >= 0) | ||
| 2799 | position = s->font->underline_position; | ||
| 2800 | else if (s->font) | ||
| 2801 | position = (s->font->descent + 1) / 2; | ||
| 2802 | else | ||
| 2803 | position = underline_minimum_offset; | ||
| 2804 | } | ||
| 2805 | position = max (position, underline_minimum_offset); | ||
| 2806 | } | ||
| 2807 | /* Check the sanity of thickness and position. We should | ||
| 2808 | avoid drawing underline out of the current line area. */ | ||
| 2809 | if (s->y + s->height <= s->ybase + position) | ||
| 2810 | position = (s->height - 1) - (s->ybase - s->y); | ||
| 2811 | if (s->y + s->height < s->ybase + position + thickness) | ||
| 2812 | thickness = (s->y + s->height) - (s->ybase + position); | ||
| 2813 | s->underline_thickness = thickness; | ||
| 2814 | s->underline_position = position; | ||
| 2815 | y = s->ybase + position; | ||
| 2816 | if (s->face->underline_defaulted_p) | ||
| 2817 | XFillRectangle (s->display, s->window, s->gc, | ||
| 2818 | s->x, y, s->width, thickness); | ||
| 2819 | else | ||
| 2820 | { | ||
| 2821 | XGCValues xgcv; | ||
| 2822 | XGetGCValues (s->display, s->gc, GCForeground, &xgcv); | ||
| 2823 | XSetForeground (s->display, s->gc, s->face->underline_color); | ||
| 2824 | XFillRectangle (s->display, s->window, s->gc, | ||
| 2825 | s->x, y, s->width, thickness); | ||
| 2826 | XSetForeground (s->display, s->gc, xgcv.foreground); | ||
| 2827 | } | ||
| 2828 | } | ||
| 2829 | 2845 | ||
| 2846 | if (s->prev && s->prev->face->underline_p) | ||
| 2847 | { | ||
| 2848 | /* We use the same underline style as the previous one. */ | ||
| 2849 | thickness = s->prev->underline_thickness; | ||
| 2850 | position = s->prev->underline_position; | ||
| 2851 | } | ||
| 2852 | else | ||
| 2853 | { | ||
| 2854 | /* Get the underline thickness. Default is 1 pixel. */ | ||
| 2855 | if (s->font && s->font->underline_thickness > 0) | ||
| 2856 | thickness = s->font->underline_thickness; | ||
| 2857 | else | ||
| 2858 | thickness = 1; | ||
| 2859 | if (x_underline_at_descent_line) | ||
| 2860 | position = (s->height - thickness) - (s->ybase - s->y); | ||
| 2861 | else | ||
| 2862 | { | ||
| 2863 | /* Get the underline position. This is the recommended | ||
| 2864 | vertical offset in pixels from the baseline to the top of | ||
| 2865 | the underline. This is a signed value according to the | ||
| 2866 | specs, and its default is | ||
| 2867 | |||
| 2868 | ROUND ((maximum descent) / 2), with | ||
| 2869 | ROUND(x) = floor (x + 0.5) */ | ||
| 2870 | |||
| 2871 | if (x_use_underline_position_properties | ||
| 2872 | && s->font && s->font->underline_position >= 0) | ||
| 2873 | position = s->font->underline_position; | ||
| 2874 | else if (s->font) | ||
| 2875 | position = (s->font->descent + 1) / 2; | ||
| 2876 | else | ||
| 2877 | position = underline_minimum_offset; | ||
| 2878 | } | ||
| 2879 | position = max (position, underline_minimum_offset); | ||
| 2880 | } | ||
| 2881 | /* Check the sanity of thickness and position. We should | ||
| 2882 | avoid drawing underline out of the current line area. */ | ||
| 2883 | if (s->y + s->height <= s->ybase + position) | ||
| 2884 | position = (s->height - 1) - (s->ybase - s->y); | ||
| 2885 | if (s->y + s->height < s->ybase + position + thickness) | ||
| 2886 | thickness = (s->y + s->height) - (s->ybase + position); | ||
| 2887 | s->underline_thickness = thickness; | ||
| 2888 | s->underline_position = position; | ||
| 2889 | y = s->ybase + position; | ||
| 2890 | if (s->face->underline_defaulted_p) | ||
| 2891 | XFillRectangle (s->display, s->window, s->gc, | ||
| 2892 | s->x, y, s->width, thickness); | ||
| 2893 | else | ||
| 2894 | { | ||
| 2895 | XGCValues xgcv; | ||
| 2896 | XGetGCValues (s->display, s->gc, GCForeground, &xgcv); | ||
| 2897 | XSetForeground (s->display, s->gc, s->face->underline_color); | ||
| 2898 | XFillRectangle (s->display, s->window, s->gc, | ||
| 2899 | s->x, y, s->width, thickness); | ||
| 2900 | XSetForeground (s->display, s->gc, xgcv.foreground); | ||
| 2901 | } | ||
| 2902 | } | ||
| 2903 | } | ||
| 2830 | /* Draw overline. */ | 2904 | /* Draw overline. */ |
| 2831 | if (s->face->overline_p) | 2905 | if (s->face->overline_p) |
| 2832 | { | 2906 | { |