Changeset 7020d1f in mainline for uspace/lib/ui/src/paint.c


Ignore:
Timestamp:
2021-02-01T10:53:48Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f14a900
Parents:
d70dc1c4
git-author:
Jiri Svoboda <jiri@…> (2020-01-31 16:53:25)
git-committer:
Jiri Svoboda <jiri@…> (2021-02-01 10:53:48)
Message:

Radio button

Please don't ask me how I derived the formulae for circle midpoint
algorithm, it's been 8 years and I just don't remember.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/src/paint.c

    rd70dc1c4 r7020d1f  
    11/*
    2  * Copyright (c) 2020 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    149149}
    150150
     151/** Paint filled circle vertical scanline.
     152 *
     153 * @param gc Graphic context
     154 * @param center Coordinates of the center of the circle
     155 * @param x X-coordinate of the scanline
     156 * @param y0 Lowest Y coordinate of the scanline (inclusive)
     157 * @param y1 Highest Y coordinate of the scanline (inclusive)
     158 * @param part Which part(s) of cicle to paint
     159 * @return EOK on success or an error code
     160 */
     161static errno_t ui_paint_fcircle_line(gfx_context_t *gc, gfx_coord2_t *center,
     162    gfx_coord_t x, gfx_coord_t y0, gfx_coord_t y1, ui_fcircle_part_t part)
     163{
     164        gfx_rect_t rect;
     165        gfx_rect_t trect;
     166
     167        rect.p0.x = x;
     168        rect.p0.y = y0;
     169        rect.p1.x = x + 1;
     170        rect.p1.y = y1;
     171
     172        /* Clip to upper-left/lower-right half of circle, if required */
     173
     174        if ((part & ui_fcircle_upleft) == 0) {
     175                if (rect.p0.y < -rect.p1.x)
     176                        rect.p0.y = -rect.p1.x;
     177        }
     178
     179        if ((part & ui_fcircle_lowright) == 0) {
     180                if (rect.p1.y > -rect.p1.x)
     181                        rect.p1.y = -rect.p1.x;
     182        }
     183
     184        /* If coordinates are reversed, there is nothing to do */
     185        if (rect.p1.y <= rect.p0.y)
     186                return EOK;
     187
     188        gfx_rect_translate(center, &rect, &trect);
     189
     190        return gfx_fill_rect(gc, &trect);
     191}
     192
     193/** Paint filled circle scanlines corresponding to octant point.
     194 *
     195 * Fills the four vertical scanlines lying between the eight reflections
     196 * of a circle point.
     197 *
     198 * @param gc Graphic context
     199 * @param center Coordinates of the center
     200 * @param r Radius in pixels
     201 * @param part Which part(s) of cicle to paint
     202 * @return EOK on success or an error code
     203 */
     204static int ui_paint_fcircle_point(gfx_context_t *gc, gfx_coord2_t *center,
     205    gfx_coord2_t *p, ui_fcircle_part_t part)
     206{
     207        errno_t rc;
     208
     209        rc = ui_paint_fcircle_line(gc, center, +p->x, -p->y, p->y + 1, part);
     210        if (rc != EOK)
     211                return rc;
     212        rc = ui_paint_fcircle_line(gc, center, -p->x, -p->y, p->y + 1, part);
     213        if (rc != EOK)
     214                return rc;
     215        rc = ui_paint_fcircle_line(gc, center, +p->y, -p->x, p->x + 1, part);
     216        if (rc != EOK)
     217                return rc;
     218        rc = ui_paint_fcircle_line(gc, center, -p->y, -p->x, p->x + 1, part);
     219        if (rc != EOK)
     220                return rc;
     221
     222        return EOK;
     223}
     224
     225/** Paint a filled circle.
     226 *
     227 * @param gc Graphic context
     228 * @param center Coordinates of the center
     229 * @param r Radius in pixels
     230 * @param part Which part(s) of cicle to paint
     231 * @return EOK on success or an error code
     232 */
     233errno_t ui_paint_filled_circle(gfx_context_t *gc, gfx_coord2_t *center,
     234    gfx_coord_t r, ui_fcircle_part_t part)
     235{
     236        gfx_coord2_t p;
     237        gfx_coord_t f;
     238        errno_t rc;
     239
     240        /* Run through one octant using circle midpoint algorithm */
     241
     242        p.x = r;
     243        p.y = 0;
     244        f = 1 - r;
     245
     246        rc = ui_paint_fcircle_point(gc, center, &p, part);
     247        if (rc != EOK)
     248                return rc;
     249
     250        while (p.x > p.y) {
     251                if (f < 0) {
     252                        f = f + 2 * p.y + 3;
     253                } else {
     254                        f = f + 2 * (p.y - p.x) + 5;
     255                        --p.x;
     256                }
     257                ++p.y;
     258
     259                rc = ui_paint_fcircle_point(gc, center, &p, part);
     260                if (rc != EOK)
     261                        return rc;
     262        }
     263
     264        return EOK;
     265}
     266
    151267/** @}
    152268 */
Note: See TracChangeset for help on using the changeset viewer.