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/w32term.c | |
| 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/w32term.c')
| -rw-r--r-- | src/w32term.c | 196 |
1 files changed, 149 insertions, 47 deletions
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. */ |