Changes in uspace/lib/ui/src/paint.c [1eaead4:81ec7e1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/paint.c
r1eaead4 r81ec7e1 1 1 /* 2 * Copyright (c) 202 3Jiri Svoboda2 * Copyright (c) 2021 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>42 41 #include <ui/paint.h> 43 42 #include <stdlib.h> … … 360 359 } 361 360 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. 361 /** Paint a text box. 637 362 * 638 363 * @param resource UI resource 639 364 * @param rect Rectangle inside which to paint the box 640 365 * @param style Box style 641 * @param boxc Box characters642 366 * @param color Color 643 367 * @return EOK on success or an error code 644 368 */ 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)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) 647 371 { 648 372 errno_t rc; … … 656 380 gfx_coord_t y; 657 381 char *str = NULL; 382 ui_box_chars_t *boxc = NULL; 658 383 659 384 gfx_rect_points_sort(rect, &srect); … … 663 388 if (dim.x < 2 || dim.y < 2) 664 389 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 resource745 * @param rect Rectangle inside which to paint the box746 * @param style Box style747 * @param color Color748 * @return EOK on success or an error code749 */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;754 390 755 391 switch (style) { … … 765 401 return EINVAL; 766 402 767 return ui_paint_text_box_custom(resource, rect, boxc, color); 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; 768 476 } 769 477 … … 811 519 812 520 gfx_text_fmt_init(&fmt); 813 fmt.font = resource->font;814 521 fmt.color = color; 815 522 … … 835 542 836 543 pos = rect->p0; 837 rc = gfx_puttext( &pos, &fmt, str);544 rc = gfx_puttext(resource->font, &pos, &fmt, str); 838 545 if (rc != EOK) 839 546 goto error; … … 847 554 } 848 555 849 /** Fill rectangle with text character.850 *851 * @param resource UI resource852 * @param rect Rectangle853 * @param color Color854 * @param gchar Character to fill with855 * @return EOK on success or an error code856 */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 function907 * first.908 *909 * @param fmt UI text formatting structure910 */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 Font919 * @param str String920 * @return Text width921 */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 characters946 * ('~'). A literal tilde can be printed with "~~". Text can be highlighted947 * with an underline or different color, based on display capabilities.948 *949 * @param pos Anchor position950 * @param fmt Text formatting951 * @param str String containing '~' markup952 *953 * @return EOK on success or an error code954 */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 1002 556 /** @} 1003 557 */
Note:
See TracChangeset
for help on using the changeset viewer.