HelenOS sources
This source file includes following definitions.
- ui_paint_bevel
- ui_paint_get_bevel_inside
- ui_paint_inset_frame
- ui_paint_get_inset_frame_inside
- ui_paint_outset_frame
- ui_paint_fcircle_line
- ui_paint_fcircle_point
- ui_paint_filled_circle
- ui_paint_up_triangle
- ui_paint_down_triangle
- ui_paint_left_triangle
- ui_paint_right_triangle
- ui_paint_cross
- ui_paint_minicon
- ui_paint_maxicon
- ui_paint_unmaxicon
- ui_paint_text_box_custom
- ui_paint_text_box
- ui_paint_text_hbrace
- ui_paint_text_rect
- ui_text_fmt_init
- ui_text_width
- ui_paint_text
#include <errno.h>
#include <gfx/color.h>
#include <gfx/context.h>
#include <gfx/render.h>
#include <gfx/text.h>
#include <ui/accel.h>
#include <ui/paint.h>
#include <stdlib.h>
#include <str.h>
#include "../private/resource.h"
static ui_box_chars_t single_box_chars = {
{
{ "\u250c", "\u2500", "\u2510" },
{ "\u2502", " ", "\u2502" },
{ "\u2514", "\u2500", "\u2518" }
}
};
static ui_box_chars_t double_box_chars = {
{
{ "\u2554", "\u2550", "\u2557" },
{ "\u2551", " ", "\u2551" },
{ "\u255a", "\u2550", "\u255d" }
}
};
static ui_brace_chars_t single_hbrace_chars = {
.start = "\u251c",
.middle = "\u2500",
.end = "\u2524"
};
static ui_brace_chars_t double_hbrace_chars = {
.start = "\u2560",
.middle = "\u2550",
.end = "\u2563"
};
errno_t ui_paint_bevel(gfx_context_t *gc, gfx_rect_t *rect,
gfx_color_t *tlcolor, gfx_color_t *brcolor, gfx_coord_t thickness,
gfx_rect_t *inside)
{
gfx_rect_t frect;
gfx_coord_t i;
errno_t rc;
rc = gfx_set_color(gc, tlcolor);
if (rc != EOK)
goto error;
for (i = 0; i < thickness; i++) {
frect.p0.x = rect->p0.x + i;
frect.p0.y = rect->p0.y + i;
frect.p1.x = rect->p1.x - i - 1;
frect.p1.y = rect->p0.y + i + 1;
rc = gfx_fill_rect(gc, &frect);
if (rc != EOK)
goto error;
frect.p0.x = rect->p0.x + i;
frect.p0.y = rect->p0.y + i + 1;
frect.p1.x = rect->p0.x + i + 1;
frect.p1.y = rect->p1.y - i - 1;
rc = gfx_fill_rect(gc, &frect);
if (rc != EOK)
goto error;
}
rc = gfx_set_color(gc, brcolor);
if (rc != EOK)
goto error;
for (i = 0; i < thickness; i++) {
frect.p0.x = rect->p0.x + i;
frect.p0.y = rect->p1.y - i - 1;
frect.p1.x = rect->p1.x - i - 1;
frect.p1.y = rect->p1.y - i;
rc = gfx_fill_rect(gc, &frect);
if (rc != EOK)
goto error;
frect.p0.x = rect->p1.x - i - 1;
frect.p0.y = rect->p0.y + i;
frect.p1.x = rect->p1.x - i;
frect.p1.y = rect->p1.y - i;
rc = gfx_fill_rect(gc, &frect);
if (rc != EOK)
goto error;
}
if (inside != NULL)
ui_paint_get_bevel_inside(gc, rect, thickness, inside);
return EOK;
error:
return rc;
}
void ui_paint_get_bevel_inside(gfx_context_t *gc, gfx_rect_t *rect,
gfx_coord_t thickness, gfx_rect_t *inside)
{
inside->p0.x = rect->p0.x + thickness;
inside->p0.y = rect->p0.y + thickness;
inside->p1.x = rect->p1.x - thickness;
inside->p1.y = rect->p1.y - thickness;
}
errno_t ui_paint_inset_frame(ui_resource_t *resource, gfx_rect_t *rect,
gfx_rect_t *inside)
{
gfx_rect_t frame;
errno_t rc;
rc = ui_paint_bevel(resource->gc, rect,
resource->wnd_shadow_color, resource->wnd_highlight_color,
1, &frame);
if (rc != EOK)
goto error;
rc = ui_paint_bevel(resource->gc, &frame,
resource->wnd_frame_sh_color, resource->wnd_frame_hi_color,
1, inside);
if (rc != EOK)
goto error;
return EOK;
error:
return rc;
}
void ui_paint_get_inset_frame_inside(ui_resource_t *resource, gfx_rect_t *rect,
gfx_rect_t *inside)
{
ui_paint_get_bevel_inside(resource->gc, rect, 2, inside);
}
errno_t ui_paint_outset_frame(ui_resource_t *resource, gfx_rect_t *rect,
gfx_rect_t *inside)
{
gfx_rect_t frame;
errno_t rc;
rc = ui_paint_bevel(resource->gc, rect,
resource->wnd_frame_hi_color, resource->wnd_frame_sh_color,
1, &frame);
if (rc != EOK)
goto error;
rc = ui_paint_bevel(resource->gc, &frame,
resource->wnd_highlight_color, resource->wnd_shadow_color,
1, inside);
if (rc != EOK)
goto error;
return EOK;
error:
return rc;
}
static errno_t ui_paint_fcircle_line(gfx_context_t *gc, gfx_coord2_t *center,
gfx_coord_t x, gfx_coord_t y0, gfx_coord_t y1, ui_fcircle_part_t part)
{
gfx_rect_t rect;
gfx_rect_t trect;
rect.p0.x = x;
rect.p0.y = y0;
rect.p1.x = x + 1;
rect.p1.y = y1;
if ((part & ui_fcircle_upleft) == 0) {
if (rect.p0.y < -rect.p1.x)
rect.p0.y = -rect.p1.x;
}
if ((part & ui_fcircle_lowright) == 0) {
if (rect.p1.y > -rect.p1.x)
rect.p1.y = -rect.p1.x;
}
if (rect.p1.y <= rect.p0.y)
return EOK;
gfx_rect_translate(center, &rect, &trect);
return gfx_fill_rect(gc, &trect);
}
static int ui_paint_fcircle_point(gfx_context_t *gc, gfx_coord2_t *center,
gfx_coord2_t *p, ui_fcircle_part_t part)
{
errno_t rc;
rc = ui_paint_fcircle_line(gc, center, +p->x, -p->y, p->y + 1, part);
if (rc != EOK)
return rc;
rc = ui_paint_fcircle_line(gc, center, -p->x, -p->y, p->y + 1, part);
if (rc != EOK)
return rc;
rc = ui_paint_fcircle_line(gc, center, +p->y, -p->x, p->x + 1, part);
if (rc != EOK)
return rc;
rc = ui_paint_fcircle_line(gc, center, -p->y, -p->x, p->x + 1, part);
if (rc != EOK)
return rc;
return EOK;
}
errno_t ui_paint_filled_circle(gfx_context_t *gc, gfx_coord2_t *center,
gfx_coord_t r, ui_fcircle_part_t part)
{
gfx_coord2_t p;
gfx_coord_t f;
errno_t rc;
p.x = r;
p.y = 0;
f = 1 - r;
rc = ui_paint_fcircle_point(gc, center, &p, part);
if (rc != EOK)
return rc;
while (p.x > p.y) {
if (f < 0) {
f = f + 2 * p.y + 3;
} else {
f = f + 2 * (p.y - p.x) + 5;
--p.x;
}
++p.y;
rc = ui_paint_fcircle_point(gc, center, &p, part);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ui_paint_up_triangle(gfx_context_t *gc, gfx_coord2_t *pos,
gfx_coord_t n)
{
gfx_coord_t i;
errno_t rc;
gfx_rect_t rect;
for (i = 0; i < n; i++) {
rect.p0.x = pos->x - i;
rect.p0.y = pos->y - n / 2 + i;
rect.p1.x = pos->x + i + 1;
rect.p1.y = pos->y - n / 2 + i + 1;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ui_paint_down_triangle(gfx_context_t *gc, gfx_coord2_t *pos,
gfx_coord_t n)
{
gfx_coord_t i;
errno_t rc;
gfx_rect_t rect;
for (i = 0; i < n; i++) {
rect.p0.x = pos->x - i;
rect.p0.y = pos->y + n / 2 - i;
rect.p1.x = pos->x + i + 1;
rect.p1.y = pos->y + n / 2 - i + 1;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ui_paint_left_triangle(gfx_context_t *gc, gfx_coord2_t *pos,
gfx_coord_t n)
{
gfx_coord_t i;
errno_t rc;
gfx_rect_t rect;
for (i = 0; i < n; i++) {
rect.p0.x = pos->x - n / 2 + i;
rect.p0.y = pos->y - i;
rect.p1.x = pos->x - n / 2 + i + 1;
rect.p1.y = pos->y + i + 1;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ui_paint_right_triangle(gfx_context_t *gc, gfx_coord2_t *pos,
gfx_coord_t n)
{
gfx_coord_t i;
errno_t rc;
gfx_rect_t rect;
for (i = 0; i < n; i++) {
rect.p0.x = pos->x + n / 2 - i;
rect.p0.y = pos->y - i;
rect.p1.x = pos->x + n / 2 - i + 1;
rect.p1.y = pos->y + i + 1;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ui_paint_cross(gfx_context_t *gc, gfx_coord2_t *pos,
gfx_coord_t n, gfx_coord_t w, gfx_coord_t h)
{
gfx_coord_t i;
gfx_rect_t rect;
errno_t rc;
rect.p0.x = pos->x;
rect.p0.y = pos->y;
rect.p1.x = pos->x + w;
rect.p1.y = pos->y + h;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
for (i = 1; i < n; i++) {
rect.p0.x = pos->x - i;
rect.p0.y = pos->y - i;
rect.p1.x = pos->x - i + w;
rect.p1.y = pos->y - i + h;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
rect.p0.x = pos->x - i;
rect.p0.y = pos->y + i;
rect.p1.x = pos->x - i + w;
rect.p1.y = pos->y + i + h;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
rect.p0.x = pos->x + i;
rect.p0.y = pos->y - i;
rect.p1.x = pos->x + i + w;
rect.p1.y = pos->y - i + h;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
rect.p0.x = pos->x + i;
rect.p0.y = pos->y + i;
rect.p1.x = pos->x + i + w;
rect.p1.y = pos->y + i + h;
rc = gfx_fill_rect(gc, &rect);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ui_paint_minicon(ui_resource_t *resource, gfx_coord2_t *pos,
gfx_coord_t w, gfx_coord_t h)
{
gfx_rect_t rect;
errno_t rc;
rc = gfx_set_color(resource->gc, resource->btn_text_color);
if (rc != EOK)
return rc;
rect.p0.x = pos->x - w / 2;
rect.p0.y = pos->y + h / 2 - 2;
rect.p1.x = rect.p0.x + w;
rect.p1.y = rect.p0.y + 2;
rc = gfx_fill_rect(resource->gc, &rect);
if (rc != EOK)
return rc;
return EOK;
}
errno_t ui_paint_maxicon(ui_resource_t *resource, gfx_coord2_t *pos,
gfx_coord_t w, gfx_coord_t h)
{
gfx_rect_t rect;
errno_t rc;
rc = gfx_set_color(resource->gc, resource->btn_text_color);
if (rc != EOK)
return rc;
rect.p0.x = pos->x - w / 2;
rect.p0.y = pos->y - h / 2;
rect.p1.x = rect.p0.x + w;
rect.p1.y = rect.p0.y + h;
rc = gfx_fill_rect(resource->gc, &rect);
if (rc != EOK)
return rc;
rc = gfx_set_color(resource->gc, resource->btn_face_color);
if (rc != EOK)
return rc;
rect.p0.x += 1;
rect.p0.y += 2;
rect.p1.x -= 1;
rect.p1.y -= 1;
rc = gfx_fill_rect(resource->gc, &rect);
if (rc != EOK)
return rc;
return EOK;
}
errno_t ui_paint_unmaxicon(ui_resource_t *resource, gfx_coord2_t *pos,
gfx_coord_t w, gfx_coord_t h, gfx_coord_t dw, gfx_coord_t dh)
{
gfx_coord2_t p;
errno_t rc;
p.x = pos->x + dw / 2;
p.y = pos->y - dh / 2;
rc = ui_paint_maxicon(resource, &p, w, h);
if (rc != EOK)
return rc;
p.x = pos->x - dw / 2;
p.y = pos->y + dh / 2;
rc = ui_paint_maxicon(resource, &p, w, h);
if (rc != EOK)
return rc;
return EOK;
}
errno_t ui_paint_text_box_custom(ui_resource_t *resource, gfx_rect_t *rect,
ui_box_chars_t *boxc, gfx_color_t *color)
{
errno_t rc;
gfx_text_fmt_t fmt;
gfx_rect_t srect;
gfx_coord2_t pos;
gfx_coord2_t dim;
size_t bufsz;
size_t off;
int i;
gfx_coord_t y;
char *str = NULL;
gfx_rect_points_sort(rect, &srect);
gfx_rect_dims(&srect, &dim);
if (dim.x < 2 || dim.y < 2)
return EOK;
gfx_text_fmt_init(&fmt);
fmt.font = resource->font;
fmt.color = color;
bufsz = str_size(boxc->c[0][0]) +
str_size(boxc->c[0][1]) * (dim.x - 2) +
str_size(boxc->c[0][2]) + 1;
str = malloc(bufsz);
if (str == NULL)
return ENOMEM;
str_cpy(str, bufsz, boxc->c[0][0]);
off = str_size(boxc->c[0][0]);
for (i = 1; i < dim.x - 1; i++) {
str_cpy(str + off, bufsz - off, boxc->c[0][1]);
off += str_size(boxc->c[0][1]);
}
str_cpy(str + off, bufsz - off, boxc->c[0][2]);
off += str_size(boxc->c[0][2]);
str[off] = '\0';
pos = rect->p0;
rc = gfx_puttext(&pos, &fmt, str);
if (rc != EOK)
goto error;
for (y = rect->p0.y + 1; y < rect->p1.y - 1; y++) {
pos.y = y;
pos.x = rect->p0.x;
rc = gfx_puttext(&pos, &fmt, boxc->c[1][0]);
if (rc != EOK)
goto error;
pos.x = rect->p1.x - 1;
rc = gfx_puttext(&pos, &fmt, boxc->c[1][2]);
if (rc != EOK)
goto error;
}
str_cpy(str, bufsz, boxc->c[2][0]);
off = str_size(boxc->c[2][0]);
for (i = 1; i < dim.x - 1; i++) {
str_cpy(str + off, bufsz - off, boxc->c[2][1]);
off += str_size(boxc->c[2][1]);
}
str_cpy(str + off, bufsz - off, boxc->c[2][2]);
off += str_size(boxc->c[2][2]);
str[off] = '\0';
pos.x = rect->p0.x;
pos.y = rect->p1.y - 1;
rc = gfx_puttext(&pos, &fmt, str);
if (rc != EOK)
goto error;
free(str);
return EOK;
error:
if (str != NULL)
free(str);
return rc;
}
errno_t ui_paint_text_box(ui_resource_t *resource, gfx_rect_t *rect,
ui_box_style_t style, gfx_color_t *color)
{
ui_box_chars_t *boxc = NULL;
switch (style) {
case ui_box_single:
boxc = &single_box_chars;
break;
case ui_box_double:
boxc = &double_box_chars;
break;
}
if (boxc == NULL)
return EINVAL;
return ui_paint_text_box_custom(resource, rect, boxc, color);
}
errno_t ui_paint_text_hbrace(ui_resource_t *resource, gfx_rect_t *rect,
ui_box_style_t style, gfx_color_t *color)
{
errno_t rc;
gfx_text_fmt_t fmt;
gfx_rect_t srect;
gfx_coord2_t pos;
gfx_coord2_t dim;
size_t bufsz;
size_t off;
int i;
char *str = NULL;
ui_brace_chars_t *hbc = NULL;
gfx_rect_points_sort(rect, &srect);
gfx_rect_dims(&srect, &dim);
if (dim.x < 2 || dim.y < 1)
return EOK;
switch (style) {
case ui_box_single:
hbc = &single_hbrace_chars;
break;
case ui_box_double:
hbc = &double_hbrace_chars;
break;
}
if (hbc == NULL)
return EINVAL;
gfx_text_fmt_init(&fmt);
fmt.font = resource->font;
fmt.color = color;
bufsz = str_size(hbc->start) +
str_size(hbc->middle) * (dim.x - 2) +
str_size(hbc->end) + 1;
str = malloc(bufsz);
if (str == NULL)
return ENOMEM;
str_cpy(str, bufsz, hbc->start);
off = str_size(hbc->start);
for (i = 1; i < dim.x - 1; i++) {
str_cpy(str + off, bufsz - off, hbc->middle);
off += str_size(hbc->middle);
}
str_cpy(str + off, bufsz - off, hbc->end);
off += str_size(hbc->end);
str[off] = '\0';
pos = rect->p0;
rc = gfx_puttext(&pos, &fmt, str);
if (rc != EOK)
goto error;
free(str);
return EOK;
error:
if (str != NULL)
free(str);
return rc;
}
errno_t ui_paint_text_rect(ui_resource_t *resource, gfx_rect_t *rect,
gfx_color_t *color, const char *gchar)
{
gfx_coord2_t pos;
gfx_text_fmt_t fmt;
gfx_rect_t srect;
gfx_coord_t w, i;
char *buf;
size_t gcharsz;
errno_t rc;
gfx_rect_points_sort(rect, &srect);
gfx_text_fmt_init(&fmt);
fmt.font = resource->font;
fmt.color = color;
fmt.halign = gfx_halign_left;
fmt.valign = gfx_valign_top;
w = srect.p1.x - srect.p0.x;
if (w == 0)
return EOK;
gcharsz = str_size(gchar);
buf = malloc(w * gcharsz + 1);
if (buf == NULL)
return ENOMEM;
for (i = 0; i < w; i++)
str_cpy(buf + i * gcharsz, (w - i) * gcharsz + 1, gchar);
buf[w * gcharsz] = '\0';
pos.x = srect.p0.x;
for (pos.y = srect.p0.y; pos.y < srect.p1.y; pos.y++) {
rc = gfx_puttext(&pos, &fmt, buf);
if (rc != EOK)
goto error;
}
free(buf);
return EOK;
error:
free(buf);
return rc;
}
void ui_text_fmt_init(ui_text_fmt_t *fmt)
{
memset(fmt, 0, sizeof(ui_text_fmt_t));
}
gfx_coord_t ui_text_width(gfx_font_t *font, const char *str)
{
gfx_coord_t w;
gfx_coord_t tw;
const char *sp;
w = gfx_text_width(font, str);
tw = gfx_text_width(font, "~");
sp = str;
while (*sp != '\0') {
if (*sp == '~' && sp[1] != '~')
w -= tw;
++sp;
}
return w;
}
errno_t ui_paint_text(gfx_coord2_t *pos, ui_text_fmt_t *fmt, const char *str)
{
gfx_coord2_t tpos;
gfx_text_fmt_t tfmt;
char *buf;
char *endptr;
const char *sp;
errno_t rc;
rc = ui_accel_process(str, &buf, &endptr);
if (rc != EOK)
return rc;
gfx_text_fmt_init(&tfmt);
tfmt.font = fmt->font;
tfmt.color = fmt->color;
tfmt.halign = fmt->halign;
tfmt.width = fmt->width;
tfmt.valign = fmt->valign;
tfmt.underline = false;
tpos = *pos;
sp = buf;
while (sp != endptr) {
rc = gfx_puttext(&tpos, &tfmt, sp);
if (rc != EOK)
goto error;
gfx_text_cont(&tpos, &tfmt, sp, &tpos, &tfmt);
tfmt.underline = !tfmt.underline;
tfmt.color = tfmt.underline ? fmt->hgl_color : fmt->color;
while (*sp != '\0')
++sp;
++sp;
}
free(buf);
return EOK;
error:
free(buf);
return rc;
}
HelenOS homepage, sources at GitHub