source: mainline/uspace/lib/guigfx/src/canvas.c@ e0545de

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

Implement bitmaps in canvas GC, demo in gfxdemo

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2019 Jiri Svoboda
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 libguigfx
30 * @{
31 */
32/**
33 * @file GFX canvas backend
34 *
35 * This implements a graphics context over a libgui canvas.
36 * This is just for experimentation purposes and its kind of backwards.
37 */
38
39#include <draw/drawctx.h>
40#include <draw/source.h>
41#include <gfx/color.h>
42#include <gfx/context.h>
43#include <gfx/render.h>
44#include <guigfx/canvas.h>
45#include <io/pixel.h>
46#include <stdlib.h>
47#include <transform.h>
48#include "../private/canvas.h"
49//#include "../../private/color.h"
50
51static errno_t canvas_gc_set_color(void *, gfx_color_t *);
52static errno_t canvas_gc_fill_rect(void *, gfx_rect_t *);
53static errno_t canvas_gc_bitmap_create(void *, gfx_bitmap_params_t *,
54 gfx_bitmap_alloc_t *, void **);
55static errno_t canvas_gc_bitmap_destroy(void *);
56static errno_t canvas_gc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
57static errno_t canvas_gc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
58
59gfx_context_ops_t canvas_gc_ops = {
60 .set_color = canvas_gc_set_color,
61 .fill_rect = canvas_gc_fill_rect,
62 .bitmap_create = canvas_gc_bitmap_create,
63 .bitmap_destroy = canvas_gc_bitmap_destroy,
64 .bitmap_render = canvas_gc_bitmap_render,
65 .bitmap_get_alloc = canvas_gc_bitmap_get_alloc
66};
67
68/** Set color on canvas GC.
69 *
70 * Set drawing color on canvas GC.
71 *
72 * @param arg Canvas GC
73 * @param color Color
74 *
75 * @return EOK on success or an error code
76 */
77static errno_t canvas_gc_set_color(void *arg, gfx_color_t *color)
78{
79 canvas_gc_t *cgc = (canvas_gc_t *) arg;
80 uint16_t r, g, b;
81
82 gfx_color_get_rgb_i16(color, &r, &g, &b);
83 cgc->color = PIXEL(0, r >> 8, g >> 8, b >> 8);
84 return EOK;
85}
86
87/** Fill rectangle on canvas GC.
88 *
89 * @param arg Canvas GC
90 * @param rect Rectangle
91 *
92 * @return EOK on success or an error code
93 */
94static errno_t canvas_gc_fill_rect(void *arg, gfx_rect_t *rect)
95{
96 canvas_gc_t *cgc = (canvas_gc_t *) arg;
97 int x, y;
98
99 // XXX We should handle p0.x > p1.x and p0.y > p1.y
100
101 for (y = rect->p0.y; y < rect->p1.y; y++) {
102 for (x = rect->p0.x; x < rect->p1.x; x++) {
103 surface_put_pixel(cgc->surface, x, y, cgc->color);
104 }
105 }
106
107 update_canvas(cgc->canvas, cgc->surface);
108
109 return EOK;
110}
111
112/** Create canvas GC.
113 *
114 * Create graphics context for rendering into a canvas.
115 *
116 * @param con Canvas object
117 * @param fout File to which characters are written (canvas)
118 * @param rgc Place to store pointer to new GC.
119 *
120 * @return EOK on success or an error code
121 */
122errno_t canvas_gc_create(canvas_t *canvas, surface_t *surface,
123 canvas_gc_t **rgc)
124{
125 canvas_gc_t *cgc = NULL;
126 gfx_context_t *gc = NULL;
127 errno_t rc;
128
129 cgc = calloc(1, sizeof(canvas_gc_t));
130 if (cgc == NULL) {
131 rc = ENOMEM;
132 goto error;
133 }
134
135 rc = gfx_context_new(&canvas_gc_ops, cgc, &gc);
136 if (rc != EOK)
137 goto error;
138
139 cgc->gc = gc;
140 cgc->canvas = canvas;
141 cgc->surface = surface;
142 *rgc = cgc;
143 return EOK;
144error:
145 if (cgc != NULL)
146 free(cgc);
147 gfx_context_delete(gc);
148 return rc;
149}
150
151/** Delete canvas GC.
152 *
153 * @param cgc Canvas GC
154 */
155errno_t canvas_gc_delete(canvas_gc_t *cgc)
156{
157 errno_t rc;
158
159 rc = gfx_context_delete(cgc->gc);
160 if (rc != EOK)
161 return rc;
162
163 free(cgc);
164 return EOK;
165}
166
167/** Get generic graphic context from canvas GC.
168 *
169 * @param cgc Canvas GC
170 * @return Graphic context
171 */
172gfx_context_t *canvas_gc_get_ctx(canvas_gc_t *cgc)
173{
174 return cgc->gc;
175}
176
177/** Create bitmap in canvas GC.
178 *
179 * @param arg Canvas GC
180 * @param params Bitmap params
181 * @param alloc Bitmap allocation info or @c NULL
182 * @param rbm Place to store pointer to new bitmap
183 * @return EOK on success or an error code
184 */
185errno_t canvas_gc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
186 gfx_bitmap_alloc_t *alloc, void **rbm)
187{
188 canvas_gc_t *cgc = (canvas_gc_t *) arg;
189 canvas_gc_bitmap_t *cbm = NULL;
190 int w, h;
191 errno_t rc;
192
193 cbm = calloc(1, sizeof(canvas_gc_bitmap_t));
194 if (cbm == NULL)
195 return ENOMEM;
196
197 w = params->rect.p1.x - params->rect.p0.x;
198 h = params->rect.p1.y - params->rect.p0.y;
199 cbm->rect = params->rect;
200
201 if (alloc == NULL) {
202 cbm->surface = surface_create(w, h, NULL, 0);
203 if (cbm->surface == NULL) {
204 rc = ENOMEM;
205 goto error;
206 }
207
208 cbm->alloc.pitch = w * sizeof(uint32_t);
209 cbm->alloc.off0 = 0;
210 cbm->alloc.pixels = surface_direct_access(cbm->surface);
211 cbm->myalloc = true;
212 } else {
213 cbm->surface = surface_create(w, h, alloc->pixels, 0);
214 if (cbm->surface == NULL) {
215 rc = ENOMEM;
216 goto error;
217 }
218
219 cbm->alloc = *alloc;
220 }
221
222 cbm->cgc = cgc;
223 *rbm = (void *)cbm;
224 return EOK;
225error:
226 if (cbm != NULL)
227 free(cbm);
228 return rc;
229}
230
231/** Destroy bitmap in canvas GC.
232 *
233 * @param bm Bitmap
234 * @return EOK on success or an error code
235 */
236static errno_t canvas_gc_bitmap_destroy(void *bm)
237{
238 canvas_gc_bitmap_t *cbm = (canvas_gc_bitmap_t *)bm;
239 if (cbm->myalloc)
240 surface_destroy(cbm->surface);
241 // XXX if !cbm->myalloc, surface is leaked - no way to destroy it
242 // without destroying the pixel buffer
243 free(cbm);
244 return EOK;
245}
246
247/** Render bitmap in canvas GC.
248 *
249 * @param bm Bitmap
250 * @param srect0 Source rectangle or @c NULL
251 * @param offs0 Offset or @c NULL
252 * @return EOK on success or an error code
253 */
254static errno_t canvas_gc_bitmap_render(void *bm, gfx_rect_t *srect0,
255 gfx_coord2_t *offs0)
256{
257 canvas_gc_bitmap_t *cbm = (canvas_gc_bitmap_t *)bm;
258 gfx_rect_t srect;
259 gfx_rect_t drect;
260 gfx_coord2_t offs;
261
262 if (srect0 != NULL)
263 srect = *srect0;
264 else
265 srect = cbm->rect;
266
267 if (offs0 != NULL) {
268 offs = *offs0;
269 } else {
270 offs.x = 0;
271 offs.y = 0;
272 }
273
274 // XXX Add function to translate rectangle
275 drect.p0.x = srect.p0.x + offs.x;
276 drect.p0.y = srect.p0.y + offs.y;
277 drect.p1.x = srect.p1.x + offs.x;
278 drect.p1.y = srect.p1.y + offs.y;
279
280 transform_t transform;
281 transform_identity(&transform);
282 transform_translate(&transform, offs.x - cbm->rect.p0.x,
283 offs.y - cbm->rect.p0.y);
284
285 source_t source;
286 source_init(&source);
287 source_set_transform(&source, transform);
288 source_set_texture(&source, cbm->surface,
289 PIXELMAP_EXTEND_TRANSPARENT_BLACK);
290
291 drawctx_t drawctx;
292 drawctx_init(&drawctx, cbm->cgc->surface);
293
294 drawctx_set_source(&drawctx, &source);
295 drawctx_transfer(&drawctx, drect.p0.x, drect.p0.y,
296 drect.p1.x - drect.p0.x, drect.p1.y - drect.p0.y);
297
298 update_canvas(cbm->cgc->canvas, cbm->cgc->surface);
299 return EOK;
300}
301
302/** Get allocation info for bitmap in canvas GC.
303 *
304 * @param bm Bitmap
305 * @param alloc Place to store allocation info
306 * @return EOK on success or an error code
307 */
308static errno_t canvas_gc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
309{
310 canvas_gc_bitmap_t *cbm = (canvas_gc_bitmap_t *)bm;
311 *alloc = cbm->alloc;
312 return EOK;
313}
314
315/** @}
316 */
Note: See TracBrowser for help on using the repository browser.