source: mainline/uspace/lib/ui/src/paint.c@ 5e109e1

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5e109e1 was d63623f, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Seeking in entry text using mouse

  • Property mode set to 100644
File size: 8.3 KB
RevLine 
[de9992c]1/*
[7020d1f]2 * Copyright (c) 2021 Jiri Svoboda
[de9992c]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libui
30 * @{
31 */
32/**
33 * @file Painting routines
34 */
35
36#include <errno.h>
37#include <gfx/color.h>
38#include <gfx/context.h>
39#include <gfx/render.h>
40#include <ui/paint.h>
[d70dc1c4]41#include "../private/resource.h"
[de9992c]42
43/** Paint bevel.
44 *
45 * @param gc Graphic context
46 * @param rect Rectangle to paint into
47 * @param tlcolor Top-left color
48 * @param brcolor Bottom-right color
49 * @param thickness Bevel thickness in pixels
50 * @param inside Place to store rectangle of the interior or @c NULL
[d63623f]51 * @return EOK on success or an error code
[de9992c]52 */
53errno_t ui_paint_bevel(gfx_context_t *gc, gfx_rect_t *rect,
54 gfx_color_t *tlcolor, gfx_color_t *brcolor, gfx_coord_t thickness,
55 gfx_rect_t *inside)
56{
57 gfx_rect_t frect;
58 gfx_coord_t i;
59 errno_t rc;
60
61 /* Top left */
62
63 rc = gfx_set_color(gc, tlcolor);
64 if (rc != EOK)
65 goto error;
66
67 for (i = 0; i < thickness; i++) {
68 frect.p0.x = rect->p0.x + i;
69 frect.p0.y = rect->p0.y + i;
70 frect.p1.x = rect->p1.x - i - 1;
71 frect.p1.y = rect->p0.y + i + 1;
72 rc = gfx_fill_rect(gc, &frect);
73 if (rc != EOK)
74 goto error;
75
76 frect.p0.x = rect->p0.x + i;
77 frect.p0.y = rect->p0.y + i + 1;
78 frect.p1.x = rect->p0.x + i + 1;
79 frect.p1.y = rect->p1.y - i - 1;
80 rc = gfx_fill_rect(gc, &frect);
81 if (rc != EOK)
82 goto error;
83 }
84
85 /* Bottom right */
86
87 rc = gfx_set_color(gc, brcolor);
88 if (rc != EOK)
89 goto error;
90
91 for (i = 0; i < thickness; i++) {
92 frect.p0.x = rect->p0.x + i;
93 frect.p0.y = rect->p1.y - i - 1;
94 frect.p1.x = rect->p1.x - i - 1;
95 frect.p1.y = rect->p1.y - i;
96 rc = gfx_fill_rect(gc, &frect);
97 if (rc != EOK)
98 goto error;
99
100 frect.p0.x = rect->p1.x - i - 1;
101 frect.p0.y = rect->p0.y + i;
102 frect.p1.x = rect->p1.x - i;
103 frect.p1.y = rect->p1.y - i;
104 rc = gfx_fill_rect(gc, &frect);
105 if (rc != EOK)
106 goto error;
107 }
108
[d63623f]109 if (inside != NULL)
110 ui_paint_get_bevel_inside(gc, rect, thickness, inside);
[de9992c]111
112 return EOK;
113error:
114 return rc;
115}
116
[d63623f]117/** Get bevel interior rectangle.
118 *
119 * Get the bevel interior rectangle without painting it.
120 *
121 * @param gc Graphic context
122 * @param rect Rectangle to paint into
123 * @param thickness Bevel thickness in pixels
124 * @param inside Place to store rectangle of the interior
125 */
126void ui_paint_get_bevel_inside(gfx_context_t *gc, gfx_rect_t *rect,
127 gfx_coord_t thickness, gfx_rect_t *inside)
128{
129 inside->p0.x = rect->p0.x + thickness;
130 inside->p0.y = rect->p0.y + thickness;
131 inside->p1.x = rect->p1.x - thickness;
132 inside->p1.y = rect->p1.y - thickness;
133}
134
[d70dc1c4]135/** Paint inset frame.
136 *
137 * @param resource UI resource
138 * @param rect Rectangle to paint onto
139 * @param inside Place to store inside rectangle or @c NULL
140 * @return EOK on success or an error code
141 */
142errno_t ui_paint_inset_frame(ui_resource_t *resource, gfx_rect_t *rect,
143 gfx_rect_t *inside)
144{
145 gfx_rect_t frame;
146 errno_t rc;
147
148 rc = ui_paint_bevel(resource->gc, rect,
149 resource->wnd_shadow_color, resource->wnd_highlight_color,
150 1, &frame);
151 if (rc != EOK)
152 goto error;
153
154 rc = ui_paint_bevel(resource->gc, &frame,
155 resource->wnd_frame_sh_color, resource->wnd_frame_hi_color,
156 1, inside);
157 if (rc != EOK)
158 goto error;
159
160 return EOK;
161error:
162 return rc;
163}
164
[d63623f]165/** Get inset frame interior rectangle.
166 *
167 * This allows one to get the interior rectangle without actually painting
168 * the inset frame.
169 *
170 * @param resource UI resource
171 * @param rect Rectangle to paint onto
172 * @param inside Place to store inside rectangle or @c NULL
173 */
174void ui_paint_get_inset_frame_inside(ui_resource_t *resource, gfx_rect_t *rect,
175 gfx_rect_t *inside)
176{
177 ui_paint_get_bevel_inside(resource->gc, rect, 2, inside);
178}
179
[214aefb]180/** Paint outset frame.
181 *
182 * @param resource UI resource
183 * @param rect Rectangle to paint onto
184 * @param inside Place to store inside rectangle or @c NULL
185 * @return EOK on success or an error code
186 */
187errno_t ui_paint_outset_frame(ui_resource_t *resource, gfx_rect_t *rect,
188 gfx_rect_t *inside)
189{
190 gfx_rect_t frame;
191 errno_t rc;
192
193 rc = ui_paint_bevel(resource->gc, rect,
194 resource->wnd_frame_hi_color, resource->wnd_frame_sh_color,
195 1, &frame);
196 if (rc != EOK)
197 goto error;
198
199 rc = ui_paint_bevel(resource->gc, &frame,
200 resource->wnd_highlight_color, resource->wnd_shadow_color,
201 1, inside);
202 if (rc != EOK)
203 goto error;
204
205 return EOK;
206error:
207 return rc;
208}
209
[7020d1f]210/** Paint filled circle vertical scanline.
211 *
212 * @param gc Graphic context
213 * @param center Coordinates of the center of the circle
214 * @param x X-coordinate of the scanline
215 * @param y0 Lowest Y coordinate of the scanline (inclusive)
216 * @param y1 Highest Y coordinate of the scanline (inclusive)
217 * @param part Which part(s) of cicle to paint
218 * @return EOK on success or an error code
219 */
220static errno_t ui_paint_fcircle_line(gfx_context_t *gc, gfx_coord2_t *center,
221 gfx_coord_t x, gfx_coord_t y0, gfx_coord_t y1, ui_fcircle_part_t part)
222{
223 gfx_rect_t rect;
224 gfx_rect_t trect;
225
226 rect.p0.x = x;
227 rect.p0.y = y0;
228 rect.p1.x = x + 1;
229 rect.p1.y = y1;
230
231 /* Clip to upper-left/lower-right half of circle, if required */
232
233 if ((part & ui_fcircle_upleft) == 0) {
234 if (rect.p0.y < -rect.p1.x)
235 rect.p0.y = -rect.p1.x;
236 }
237
238 if ((part & ui_fcircle_lowright) == 0) {
239 if (rect.p1.y > -rect.p1.x)
240 rect.p1.y = -rect.p1.x;
241 }
242
243 /* If coordinates are reversed, there is nothing to do */
244 if (rect.p1.y <= rect.p0.y)
245 return EOK;
246
247 gfx_rect_translate(center, &rect, &trect);
248
249 return gfx_fill_rect(gc, &trect);
250}
251
252/** Paint filled circle scanlines corresponding to octant point.
253 *
254 * Fills the four vertical scanlines lying between the eight reflections
255 * of a circle point.
256 *
257 * @param gc Graphic context
258 * @param center Coordinates of the center
259 * @param r Radius in pixels
260 * @param part Which part(s) of cicle to paint
261 * @return EOK on success or an error code
262 */
263static int ui_paint_fcircle_point(gfx_context_t *gc, gfx_coord2_t *center,
264 gfx_coord2_t *p, ui_fcircle_part_t part)
265{
266 errno_t rc;
267
268 rc = ui_paint_fcircle_line(gc, center, +p->x, -p->y, p->y + 1, part);
269 if (rc != EOK)
270 return rc;
271 rc = ui_paint_fcircle_line(gc, center, -p->x, -p->y, p->y + 1, part);
272 if (rc != EOK)
273 return rc;
274 rc = ui_paint_fcircle_line(gc, center, +p->y, -p->x, p->x + 1, part);
275 if (rc != EOK)
276 return rc;
277 rc = ui_paint_fcircle_line(gc, center, -p->y, -p->x, p->x + 1, part);
278 if (rc != EOK)
279 return rc;
280
281 return EOK;
282}
283
284/** Paint a filled circle.
285 *
286 * @param gc Graphic context
287 * @param center Coordinates of the center
288 * @param r Radius in pixels
289 * @param part Which part(s) of cicle to paint
290 * @return EOK on success or an error code
291 */
292errno_t ui_paint_filled_circle(gfx_context_t *gc, gfx_coord2_t *center,
293 gfx_coord_t r, ui_fcircle_part_t part)
294{
295 gfx_coord2_t p;
296 gfx_coord_t f;
297 errno_t rc;
298
299 /* Run through one octant using circle midpoint algorithm */
300
301 p.x = r;
302 p.y = 0;
303 f = 1 - r;
304
305 rc = ui_paint_fcircle_point(gc, center, &p, part);
306 if (rc != EOK)
307 return rc;
308
309 while (p.x > p.y) {
310 if (f < 0) {
311 f = f + 2 * p.y + 3;
312 } else {
313 f = f + 2 * (p.y - p.x) + 5;
314 --p.x;
315 }
316 ++p.y;
317
318 rc = ui_paint_fcircle_point(gc, center, &p, part);
319 if (rc != EOK)
320 return rc;
321 }
322
323 return EOK;
324}
325
[de9992c]326/** @}
327 */
Note: See TracBrowser for help on using the repository browser.