Changes in uspace/lib/ui/src/paint.c [81ec7e1:1eaead4] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/paint.c
r81ec7e1 r1eaead4 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2023 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 39 39 #include <gfx/render.h> 40 40 #include <gfx/text.h> 41 #include <ui/accel.h> 41 42 #include <ui/paint.h> 42 43 #include <stdlib.h> … … 359 360 } 360 361 361 /** Paint a text box. 362 /** Paint upward pointing triangle. 363 * 364 * @param gc Graphic context 365 * @param pos Center position 366 * @param n Length of triangle side 367 * @return EOK on success or an error code 368 */ 369 errno_t ui_paint_up_triangle(gfx_context_t *gc, gfx_coord2_t *pos, 370 gfx_coord_t n) 371 { 372 gfx_coord_t i; 373 errno_t rc; 374 gfx_rect_t rect; 375 376 for (i = 0; i < n; i++) { 377 rect.p0.x = pos->x - i; 378 rect.p0.y = pos->y - n / 2 + i; 379 rect.p1.x = pos->x + i + 1; 380 rect.p1.y = pos->y - n / 2 + i + 1; 381 rc = gfx_fill_rect(gc, &rect); 382 if (rc != EOK) 383 return rc; 384 } 385 386 return EOK; 387 } 388 389 /** Paint downward pointing triangle. 390 * 391 * @param gc Graphic context 392 * @param pos Center position 393 * @param n Length of triangle side 394 * @return EOK on success or an error code 395 */ 396 errno_t ui_paint_down_triangle(gfx_context_t *gc, gfx_coord2_t *pos, 397 gfx_coord_t n) 398 { 399 gfx_coord_t i; 400 errno_t rc; 401 gfx_rect_t rect; 402 403 for (i = 0; i < n; i++) { 404 rect.p0.x = pos->x - i; 405 rect.p0.y = pos->y + n / 2 - i; 406 rect.p1.x = pos->x + i + 1; 407 rect.p1.y = pos->y + n / 2 - i + 1; 408 rc = gfx_fill_rect(gc, &rect); 409 if (rc != EOK) 410 return rc; 411 } 412 413 return EOK; 414 } 415 416 /** Paint left pointing triangle. 417 * 418 * @param gc Graphic context 419 * @param pos Center position 420 * @param n Length of triangle side 421 * @return EOK on success or an error code 422 */ 423 errno_t ui_paint_left_triangle(gfx_context_t *gc, gfx_coord2_t *pos, 424 gfx_coord_t n) 425 { 426 gfx_coord_t i; 427 errno_t rc; 428 gfx_rect_t rect; 429 430 for (i = 0; i < n; i++) { 431 rect.p0.x = pos->x - n / 2 + i; 432 rect.p0.y = pos->y - i; 433 rect.p1.x = pos->x - n / 2 + i + 1; 434 rect.p1.y = pos->y + i + 1; 435 rc = gfx_fill_rect(gc, &rect); 436 if (rc != EOK) 437 return rc; 438 } 439 440 return EOK; 441 } 442 443 /** Paint right pointing triangle. 444 * 445 * @param gc Graphic context 446 * @param pos Center position 447 * @param n Length of triangle side 448 * @return EOK on success or an error code 449 */ 450 errno_t ui_paint_right_triangle(gfx_context_t *gc, gfx_coord2_t *pos, 451 gfx_coord_t n) 452 { 453 gfx_coord_t i; 454 errno_t rc; 455 gfx_rect_t rect; 456 457 for (i = 0; i < n; i++) { 458 rect.p0.x = pos->x + n / 2 - i; 459 rect.p0.y = pos->y - i; 460 rect.p1.x = pos->x + n / 2 - i + 1; 461 rect.p1.y = pos->y + i + 1; 462 rc = gfx_fill_rect(gc, &rect); 463 if (rc != EOK) 464 return rc; 465 } 466 467 return EOK; 468 } 469 470 /** Paint diagonal cross (X). 471 * 472 * @param gc Graphic context 473 * @param pos Center position 474 * @param n Length of each leg 475 * @param w Pen width 476 * @param h Pen height 477 * @return EOK on success or an error code 478 */ 479 errno_t ui_paint_cross(gfx_context_t *gc, gfx_coord2_t *pos, 480 gfx_coord_t n, gfx_coord_t w, gfx_coord_t h) 481 { 482 gfx_coord_t i; 483 gfx_rect_t rect; 484 errno_t rc; 485 486 rect.p0.x = pos->x; 487 rect.p0.y = pos->y; 488 rect.p1.x = pos->x + w; 489 rect.p1.y = pos->y + h; 490 rc = gfx_fill_rect(gc, &rect); 491 if (rc != EOK) 492 return rc; 493 494 for (i = 1; i < n; i++) { 495 rect.p0.x = pos->x - i; 496 rect.p0.y = pos->y - i; 497 rect.p1.x = pos->x - i + w; 498 rect.p1.y = pos->y - i + h; 499 rc = gfx_fill_rect(gc, &rect); 500 if (rc != EOK) 501 return rc; 502 503 rect.p0.x = pos->x - i; 504 rect.p0.y = pos->y + i; 505 rect.p1.x = pos->x - i + w; 506 rect.p1.y = pos->y + i + h; 507 rc = gfx_fill_rect(gc, &rect); 508 if (rc != EOK) 509 return rc; 510 511 rect.p0.x = pos->x + i; 512 rect.p0.y = pos->y - i; 513 rect.p1.x = pos->x + i + w; 514 rect.p1.y = pos->y - i + h; 515 rc = gfx_fill_rect(gc, &rect); 516 if (rc != EOK) 517 return rc; 518 519 rect.p0.x = pos->x + i; 520 rect.p0.y = pos->y + i; 521 rect.p1.x = pos->x + i + w; 522 rect.p1.y = pos->y + i + h; 523 rc = gfx_fill_rect(gc, &rect); 524 if (rc != EOK) 525 return rc; 526 } 527 528 return EOK; 529 } 530 531 /** Paint minimize icon. 532 * 533 * @param resource UI resource 534 * @param pos Center position 535 * @param w Icon width 536 * @param h Icon height 537 * @return EOK on success or an error code 538 */ 539 errno_t ui_paint_minicon(ui_resource_t *resource, gfx_coord2_t *pos, 540 gfx_coord_t w, gfx_coord_t h) 541 { 542 gfx_rect_t rect; 543 errno_t rc; 544 545 rc = gfx_set_color(resource->gc, resource->btn_text_color); 546 if (rc != EOK) 547 return rc; 548 549 rect.p0.x = pos->x - w / 2; 550 rect.p0.y = pos->y + h / 2 - 2; 551 rect.p1.x = rect.p0.x + w; 552 rect.p1.y = rect.p0.y + 2; 553 rc = gfx_fill_rect(resource->gc, &rect); 554 if (rc != EOK) 555 return rc; 556 557 return EOK; 558 } 559 560 /** Paint maximize icon. 561 * 562 * @param resource UI resource 563 * @param pos Center position 564 * @param w Icon width 565 * @param h Icon height 566 * @return EOK on success or an error code 567 */ 568 errno_t ui_paint_maxicon(ui_resource_t *resource, gfx_coord2_t *pos, 569 gfx_coord_t w, gfx_coord_t h) 570 { 571 gfx_rect_t rect; 572 errno_t rc; 573 574 rc = gfx_set_color(resource->gc, resource->btn_text_color); 575 if (rc != EOK) 576 return rc; 577 578 rect.p0.x = pos->x - w / 2; 579 rect.p0.y = pos->y - h / 2; 580 rect.p1.x = rect.p0.x + w; 581 rect.p1.y = rect.p0.y + h; 582 rc = gfx_fill_rect(resource->gc, &rect); 583 if (rc != EOK) 584 return rc; 585 586 rc = gfx_set_color(resource->gc, resource->btn_face_color); 587 if (rc != EOK) 588 return rc; 589 590 rect.p0.x += 1; 591 rect.p0.y += 2; 592 rect.p1.x -= 1; 593 rect.p1.y -= 1; 594 rc = gfx_fill_rect(resource->gc, &rect); 595 if (rc != EOK) 596 return rc; 597 598 return EOK; 599 } 600 601 /** Paint unmaximize icon. 602 * 603 * Unmaximize icon consists of two overlapping window icons. 604 * 605 * @param resource UI resource 606 * @param pos Center position 607 * @param w Window icon width 608 * @param h Window icon height 609 * @param dw Horizontal distance between window icon centers 610 * @param dh Vertical distance between window icon centers 611 * @return EOK on success or an error code 612 */ 613 errno_t ui_paint_unmaxicon(ui_resource_t *resource, gfx_coord2_t *pos, 614 gfx_coord_t w, gfx_coord_t h, gfx_coord_t dw, gfx_coord_t dh) 615 { 616 gfx_coord2_t p; 617 errno_t rc; 618 619 p.x = pos->x + dw / 2; 620 p.y = pos->y - dh / 2; 621 rc = ui_paint_maxicon(resource, &p, w, h); 622 if (rc != EOK) 623 return rc; 624 625 p.x = pos->x - dw / 2; 626 p.y = pos->y + dh / 2; 627 rc = ui_paint_maxicon(resource, &p, w, h); 628 if (rc != EOK) 629 return rc; 630 631 return EOK; 632 } 633 634 /** Paint a custom text box. 635 * 636 * Paint a text box using user-provided box chars. 362 637 * 363 638 * @param resource UI resource 364 639 * @param rect Rectangle inside which to paint the box 365 640 * @param style Box style 641 * @param boxc Box characters 366 642 * @param color Color 367 643 * @return EOK on success or an error code 368 644 */ 369 errno_t ui_paint_text_box (ui_resource_t *resource, gfx_rect_t *rect,370 ui_box_ style_t style, gfx_color_t *color)645 errno_t ui_paint_text_box_custom(ui_resource_t *resource, gfx_rect_t *rect, 646 ui_box_chars_t *boxc, gfx_color_t *color) 371 647 { 372 648 errno_t rc; … … 380 656 gfx_coord_t y; 381 657 char *str = NULL; 382 ui_box_chars_t *boxc = NULL;383 658 384 659 gfx_rect_points_sort(rect, &srect); … … 388 663 if (dim.x < 2 || dim.y < 2) 389 664 return EOK; 665 666 gfx_text_fmt_init(&fmt); 667 fmt.font = resource->font; 668 fmt.color = color; 669 670 bufsz = str_size(boxc->c[0][0]) + 671 str_size(boxc->c[0][1]) * (dim.x - 2) + 672 str_size(boxc->c[0][2]) + 1; 673 674 str = malloc(bufsz); 675 if (str == NULL) 676 return ENOMEM; 677 678 /* Top edge and corners */ 679 680 str_cpy(str, bufsz, boxc->c[0][0]); 681 off = str_size(boxc->c[0][0]); 682 683 for (i = 1; i < dim.x - 1; i++) { 684 str_cpy(str + off, bufsz - off, boxc->c[0][1]); 685 off += str_size(boxc->c[0][1]); 686 } 687 688 str_cpy(str + off, bufsz - off, boxc->c[0][2]); 689 off += str_size(boxc->c[0][2]); 690 str[off] = '\0'; 691 692 pos = rect->p0; 693 rc = gfx_puttext(&pos, &fmt, str); 694 if (rc != EOK) 695 goto error; 696 697 /* Vertical edges */ 698 for (y = rect->p0.y + 1; y < rect->p1.y - 1; y++) { 699 pos.y = y; 700 701 pos.x = rect->p0.x; 702 rc = gfx_puttext(&pos, &fmt, boxc->c[1][0]); 703 if (rc != EOK) 704 goto error; 705 706 pos.x = rect->p1.x - 1; 707 rc = gfx_puttext(&pos, &fmt, boxc->c[1][2]); 708 if (rc != EOK) 709 goto error; 710 } 711 712 /* Bottom edge and corners */ 713 714 str_cpy(str, bufsz, boxc->c[2][0]); 715 off = str_size(boxc->c[2][0]); 716 717 for (i = 1; i < dim.x - 1; i++) { 718 str_cpy(str + off, bufsz - off, boxc->c[2][1]); 719 off += str_size(boxc->c[2][1]); 720 } 721 722 str_cpy(str + off, bufsz - off, boxc->c[2][2]); 723 off += str_size(boxc->c[2][2]); 724 str[off] = '\0'; 725 726 pos.x = rect->p0.x; 727 pos.y = rect->p1.y - 1; 728 rc = gfx_puttext(&pos, &fmt, str); 729 if (rc != EOK) 730 goto error; 731 732 free(str); 733 return EOK; 734 error: 735 if (str != NULL) 736 free(str); 737 return rc; 738 } 739 740 /** Paint a text box. 741 * 742 * Paint a text box with the specified style. 743 * 744 * @param resource UI resource 745 * @param rect Rectangle inside which to paint the box 746 * @param style Box style 747 * @param color Color 748 * @return EOK on success or an error code 749 */ 750 errno_t ui_paint_text_box(ui_resource_t *resource, gfx_rect_t *rect, 751 ui_box_style_t style, gfx_color_t *color) 752 { 753 ui_box_chars_t *boxc = NULL; 390 754 391 755 switch (style) { … … 401 765 return EINVAL; 402 766 403 gfx_text_fmt_init(&fmt); 404 fmt.color = color; 405 406 bufsz = str_size(boxc->c[0][0]) + 407 str_size(boxc->c[0][1]) * (dim.x - 2) + 408 str_size(boxc->c[0][2]) + 1; 409 410 str = malloc(bufsz); 411 if (str == NULL) 412 return ENOMEM; 413 414 /* Top edge and corners */ 415 416 str_cpy(str, bufsz, boxc->c[0][0]); 417 off = str_size(boxc->c[0][0]); 418 419 for (i = 1; i < dim.x - 1; i++) { 420 str_cpy(str + off, bufsz - off, boxc->c[0][1]); 421 off += str_size(boxc->c[0][1]); 422 } 423 424 str_cpy(str + off, bufsz - off, boxc->c[0][2]); 425 off += str_size(boxc->c[0][2]); 426 str[off] = '\0'; 427 428 pos = rect->p0; 429 rc = gfx_puttext(resource->font, &pos, &fmt, str); 430 if (rc != EOK) 431 goto error; 432 433 /* Vertical edges */ 434 for (y = rect->p0.y + 1; y < rect->p1.y - 1; y++) { 435 pos.y = y; 436 437 pos.x = rect->p0.x; 438 rc = gfx_puttext(resource->font, &pos, &fmt, 439 boxc->c[1][0]); 440 if (rc != EOK) 441 goto error; 442 443 pos.x = rect->p1.x - 1; 444 rc = gfx_puttext(resource->font, &pos, &fmt, 445 boxc->c[1][2]); 446 if (rc != EOK) 447 goto error; 448 } 449 450 /* Bottom edge and corners */ 451 452 str_cpy(str, bufsz, boxc->c[2][0]); 453 off = str_size(boxc->c[2][0]); 454 455 for (i = 1; i < dim.x - 1; i++) { 456 str_cpy(str + off, bufsz - off, boxc->c[2][1]); 457 off += str_size(boxc->c[2][1]); 458 } 459 460 str_cpy(str + off, bufsz - off, boxc->c[2][2]); 461 off += str_size(boxc->c[2][2]); 462 str[off] = '\0'; 463 464 pos.x = rect->p0.x; 465 pos.y = rect->p1.y - 1; 466 rc = gfx_puttext(resource->font, &pos, &fmt, str); 467 if (rc != EOK) 468 goto error; 469 470 free(str); 471 return EOK; 472 error: 473 if (str != NULL) 474 free(str); 475 return rc; 767 return ui_paint_text_box_custom(resource, rect, boxc, color); 476 768 } 477 769 … … 519 811 520 812 gfx_text_fmt_init(&fmt); 813 fmt.font = resource->font; 521 814 fmt.color = color; 522 815 … … 542 835 543 836 pos = rect->p0; 544 rc = gfx_puttext( resource->font,&pos, &fmt, str);837 rc = gfx_puttext(&pos, &fmt, str); 545 838 if (rc != EOK) 546 839 goto error; … … 554 847 } 555 848 849 /** Fill rectangle with text character. 850 * 851 * @param resource UI resource 852 * @param rect Rectangle 853 * @param color Color 854 * @param gchar Character to fill with 855 * @return EOK on success or an error code 856 */ 857 errno_t ui_paint_text_rect(ui_resource_t *resource, gfx_rect_t *rect, 858 gfx_color_t *color, const char *gchar) 859 { 860 gfx_coord2_t pos; 861 gfx_text_fmt_t fmt; 862 gfx_rect_t srect; 863 gfx_coord_t w, i; 864 char *buf; 865 size_t gcharsz; 866 errno_t rc; 867 868 gfx_rect_points_sort(rect, &srect); 869 870 gfx_text_fmt_init(&fmt); 871 fmt.font = resource->font; 872 fmt.color = color; 873 fmt.halign = gfx_halign_left; 874 fmt.valign = gfx_valign_top; 875 876 w = srect.p1.x - srect.p0.x; 877 if (w == 0) 878 return EOK; 879 880 gcharsz = str_size(gchar); 881 882 buf = malloc(w * gcharsz + 1); 883 if (buf == NULL) 884 return ENOMEM; 885 886 for (i = 0; i < w; i++) 887 str_cpy(buf + i * gcharsz, (w - i) * gcharsz + 1, gchar); 888 buf[w * gcharsz] = '\0'; 889 890 pos.x = srect.p0.x; 891 for (pos.y = srect.p0.y; pos.y < srect.p1.y; pos.y++) { 892 rc = gfx_puttext(&pos, &fmt, buf); 893 if (rc != EOK) 894 goto error; 895 } 896 897 free(buf); 898 return EOK; 899 error: 900 free(buf); 901 return rc; 902 } 903 904 /** Initialize UI text formatting structure. 905 * 906 * UI text formatting structure must always be initialized using this function 907 * first. 908 * 909 * @param fmt UI text formatting structure 910 */ 911 void ui_text_fmt_init(ui_text_fmt_t *fmt) 912 { 913 memset(fmt, 0, sizeof(ui_text_fmt_t)); 914 } 915 916 /** Compute UI text width. 917 * 918 * @param font Font 919 * @param str String 920 * @return Text width 921 */ 922 gfx_coord_t ui_text_width(gfx_font_t *font, const char *str) 923 { 924 gfx_coord_t w; 925 gfx_coord_t tw; 926 const char *sp; 927 928 /* Text including tildes */ 929 w = gfx_text_width(font, str); 930 tw = gfx_text_width(font, "~"); 931 932 /* Subtract width of singular tildes */ 933 sp = str; 934 while (*sp != '\0') { 935 if (*sp == '~' && sp[1] != '~') 936 w -= tw; 937 ++sp; 938 } 939 940 return w; 941 } 942 943 /** Paint text (with highlighting markup). 944 * 945 * Paint some text with highlighted sections enclosed with tilde characters 946 * ('~'). A literal tilde can be printed with "~~". Text can be highlighted 947 * with an underline or different color, based on display capabilities. 948 * 949 * @param pos Anchor position 950 * @param fmt Text formatting 951 * @param str String containing '~' markup 952 * 953 * @return EOK on success or an error code 954 */ 955 errno_t ui_paint_text(gfx_coord2_t *pos, ui_text_fmt_t *fmt, const char *str) 956 { 957 gfx_coord2_t tpos; 958 gfx_text_fmt_t tfmt; 959 char *buf; 960 char *endptr; 961 const char *sp; 962 errno_t rc; 963 964 /* Break down string into list of (non)highlighted parts */ 965 rc = ui_accel_process(str, &buf, &endptr); 966 if (rc != EOK) 967 return rc; 968 969 gfx_text_fmt_init(&tfmt); 970 tfmt.font = fmt->font; 971 tfmt.color = fmt->color; 972 tfmt.halign = fmt->halign; 973 tfmt.width = fmt->width; 974 tfmt.valign = fmt->valign; 975 tfmt.underline = false; 976 977 tpos = *pos; 978 sp = buf; 979 while (sp != endptr) { 980 /* Print the current string */ 981 rc = gfx_puttext(&tpos, &tfmt, sp); 982 if (rc != EOK) 983 goto error; 984 985 gfx_text_cont(&tpos, &tfmt, sp, &tpos, &tfmt); 986 tfmt.underline = !tfmt.underline; 987 tfmt.color = tfmt.underline ? fmt->hgl_color : fmt->color; 988 989 /* Skip to the next string */ 990 while (*sp != '\0') 991 ++sp; 992 ++sp; 993 } 994 995 free(buf); 996 return EOK; 997 error: 998 free(buf); 999 return rc; 1000 } 1001 556 1002 /** @} 557 1003 */
Note:
See TracChangeset
for help on using the changeset viewer.