1/*
2 * lws abstract display
3 *
4 * Copyright (C) 2019 - 2022 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * lws display_list and display_list objects (dlo)
25 */
26
27#if !defined(__LWS_DLO_H__)
28#define __LWS_DLO_H__
29
30#include <stdint.h>
31
32struct lws_display_render_state;
33struct lws_surface_info;
34struct lws_display_state;
35struct lws_display_font;
36struct lws_dlo_text;
37struct lws_display;
38struct lws_dlo_text;
39struct lws_dlo;
40
41#define LWSDC_RGBA(_r, _g, _b, _a) (((uint32_t)(_r) & 0xff) | \
42 (((uint32_t)(_g) & 0xff) << 8) | \
43 (((uint32_t)(_b) & 0xff) << 16) | \
44 (((uint32_t)(_a) & 0xff) << 24))
45
46#define LWSDC_R(_c) ((_c) & 0xff)
47#define LWSDC_G(_c) ((_c >> 8) & 0xff)
48#define LWSDC_B(_c) ((_c >> 16) & 0xff)
49#define LWSDC_ALPHA(_c) ((_c >> 24) & 0xff)
50
51#define RGB_TO_Y(_r, _g, _b) ((((_r) * 299) + ((_g) * 587) + ((_b) * 114)) / 1000)
52/* stores Y in RGBY */
53#define PALETTE_RGBY(_r, _g, _b) LWSDC_RGBA(_r, _g, _b, (RGB_TO_Y(_r, _g, _b)))
54
55typedef struct {
56 lws_fx_t w;
57 lws_fx_t h;
58} lws_dlo_dim_t;
59
60/*
61 * When using RGBA to describe native greyscale, R is Y and A is A, GB is ignored
62 */
63
64/* composed at start of larger, font-specific glyph struct */
65
66typedef struct lws_font_glyph {
67 lws_dll2_t list;
68
69 lws_fx_t xorg;
70 lws_fx_t xpx;
71 lws_fx_t height;
72 lws_fx_t cwidth;
73
74 int8_t x; /* x offset inside the glyph */
75
76} lws_font_glyph_t;
77
78typedef lws_stateful_ret_t (*lws_dlo_renderer_t)(struct lws_display_render_state *rs);
79typedef lws_font_glyph_t * (*lws_dlo_image_glyph_t)(
80 struct lws_dlo_text *text,
81 uint32_t unicode, char attach);
82typedef void (*lws_dlo_destroy_t)(struct lws_dlo *dlo);
83
84typedef struct lws_display_id {
85 lws_dll2_t list;
86
87 char id[16];
88 lws_box_t box; /* taken from DLO after layout */
89
90 void *priv_user;
91 void *priv_driver;
92
93 char exists;
94 char iframe; /* 1 = render html as if partial
95 * is the origin, otherwise
96 * render html with surface
97 * (0,0) as origin and rs->box
98 * is a viewport on to that */
99} lws_display_id_t;
100
101/*
102 * Common dlo object that joins the display list, composed into a subclass
103 * object like lws_dlo_rect_t etc
104 */
105
106typedef struct lws_dlo {
107 lws_dll2_t list;
108
109 lws_dll2_t col_list; /* lws_dlo_t: column-mates */
110 lws_dll2_t row_list; /* lws_dlo_t: row-mates */
111
112 /* children are rendered "inside" the parent DLO box after allowing
113 * for parent padding */
114 lws_dll2_owner_t children;
115
116 /* only used for dlo rect representing whole table */
117
118 lws_dll2_owner_t table_cols; /* lhp_table_col_t */
119 lws_dll2_owner_t table_rows; /* lhp_table_row_t */
120
121 /* may point to dlo whose width or height decides our x or y */
122
123 struct lws_dlo *abut_x;
124 struct lws_dlo *abut_y;
125
126 lws_dlo_destroy_t _destroy; /* dlo-type specific cb */
127 lws_dlo_renderer_t render; /* dlo-type specific cb */
128
129 lws_fx_t margin[4];
130 lws_fx_t padding[4]; /* child origin */
131
132 lws_display_id_t *id; /* only valid until ids destroyed */
133
134 lws_box_t box;
135 lws_display_colour_t dc;
136
137 uint8_t flag_runon:1; /* continues same line */
138 uint8_t flag_done_align:1;
139 uint8_t flag_toplevel:1; /* don't scan up with me (different owner) */
140
141 /* render-specific members ... */
142} lws_dlo_t;
143
144typedef struct lws_circle {
145 lws_fx_t r;
146
147 /* rasterization temps */
148 lws_fx_t orx; /* abs pixel x for centre */
149 lws_fx_t ory; /* abs pixel y for centre */
150 lws_fx_t rsq;
151 lws_fx_t ys;
152} lws_circle_t;
153
154typedef struct lws_dlo_rect {
155 lws_dlo_t dlo;
156 lws_circle_t c[4]; /* t-l, t-r, b-l, b-r */
157 lws_fx_t b[4]; /* border width on t/r/b/l */
158 lws_display_colour_t dcb; /* border colour */
159
160 /* rasterization temps */
161
162 lws_fx_t btm;
163 lws_fx_t right;
164 lws_box_t db;
165
166 uint8_t init;
167 uint8_t alt;
168} lws_dlo_rect_t;
169
170typedef struct lws_dlo_circle {
171 lws_dlo_t dlo;
172} lws_dlo_circle_t;
173
174typedef struct lws_font_choice {
175 const char *family_name;
176 const char *generic_name;
177 uint16_t weight;
178 uint16_t style; /* normal, italic, oblique */
179 uint16_t fixed_height;
180} lws_font_choice_t;
181
182typedef struct lws_display_font {
183 lws_dll2_t list;
184
185 lws_font_choice_t choice;
186
187 const uint8_t *data; /* may be cast to imp struct */
188 uint8_t *priv; /* only used by implementation */
189 size_t data_len;
190 lws_dlo_renderer_t renderer;
191 lws_dlo_image_glyph_t image_glyph;
192
193 lws_fx_t em; /* 1 em in pixels */
194 lws_fx_t ex; /* 1 ex in pixels */
195} lws_display_font_t;
196
197typedef struct lws_dlo_filesystem {
198 lws_dll2_t list;
199
200 const char *name;
201 const void *data;
202 size_t len;
203} lws_dlo_filesystem_t;
204
205#define LWSDLO_TEXT_FLAG_WRAP (1 << 0)
206
207typedef struct lws_dlo_text {
208 lws_dlo_t dlo;
209 const lws_display_font_t *font;
210 lws_dll2_owner_t glyphs;
211 lws_box_t bounding_box; /* { 0, 0, w, h } relative
212 * to and subject to
213 * clipping by .dlo.box */
214
215 /* referred to by glyphs */
216 const struct lws_surface_info *ic;
217 struct lwsac *ac_glyphs;
218 uint8_t *line;
219 uint16_t curr;
220
221 char *text;
222 uint8_t *kern;
223 size_t text_len;
224 lws_display_list_coord_t clkernpx;
225 lws_display_list_coord_t cwidth;
226
227 lws_fx_t indent;
228
229 uint32_t flags;
230 int16_t font_y_baseline;
231 int16_t font_height;
232 int16_t font_line_height;
233
234 int16_t group_height;
235 int16_t group_y_baseline;
236
237 lws_fx_t _cwidth;
238} lws_dlo_text_t;
239
240typedef struct lws_dlo_rasterize {
241 lws_dll2_owner_t owner; /* lws_flow_t */
242 lws_sorted_usec_list_t sul;
243 int lines;
244} lws_dlo_rasterize_t;
245
246typedef struct lws_dlo_png {
247 lws_dlo_t dlo; /* ordering: first */
248 lws_flow_t flow; /* ordering: second */
249 lws_upng_t *png;
250} lws_dlo_png_t;
251
252typedef struct lws_dlo_jpeg {
253 lws_dlo_t dlo; /* ordering: first */
254 lws_flow_t flow; /* ordering: second */
255 lws_jpeg_t *j;
256} lws_dlo_jpeg_t;
257
258typedef enum {
259 LWSDLOSS_TYPE_JPEG,
260 LWSDLOSS_TYPE_PNG,
261 LWSDLOSS_TYPE_CSS,
262} lws_dlo_image_type_t;
263
264typedef struct {
265 union {
266 lws_dlo_jpeg_t *dlo_jpeg;
267 lws_dlo_png_t *dlo_png;
268 } u;
269 lws_dlo_image_type_t type;
270 char failed;
271} lws_dlo_image_t;
272
273typedef struct lws_displaylist {
274 lws_dll2_owner_t dl;
275 struct lws_display_state *ds;
276} lws_displaylist_t;
277
278typedef struct lws_dl_rend {
279 lws_displaylist_t *dl;
280 int w;
281 int h;
282} lws_dl_rend_t;
283
284typedef struct lws_display_render_stack {
285 lws_dlo_t *dlo; /* position in dlo owner */
286 lws_box_t co; /* our origin as parent */
287} lws_display_render_stack_t;
288
289typedef struct lws_display_render_state {
290 lws_sorted_usec_list_t sul; /* return to event loop statefully */
291 struct lws_display_state *lds; /* optional, if using lws_display */
292
293 lws_dll2_owner_t ids;
294
295 const struct lws_surface_info *ic; /* display dimensions, palette */
296
297 lws_display_render_stack_t st[12]; /* DLO child stack */
298 int sp; /* DLO child stack level */
299
300 uint8_t *line; /* Y or RGB line comp buffer */
301
302 lws_displaylist_t displaylist;
303
304 lws_display_scalar curr;
305 lws_display_scalar lowest_id_y;
306
307 char html;
308
309} lws_display_render_state_t;
310
311
312LWS_VISIBLE LWS_EXTERN void
313lws_display_render_free_ids(lws_display_render_state_t *rs);
314
315LWS_VISIBLE LWS_EXTERN lws_display_id_t *
316lws_display_render_add_id(lws_display_render_state_t *rs, const char *id, void *priv);
317
318LWS_VISIBLE LWS_EXTERN lws_display_id_t *
319lws_display_render_get_id(lws_display_render_state_t *rs, const char *id);
320
321LWS_VISIBLE LWS_EXTERN void
322lws_display_render_dump_ids(lws_dll2_owner_t *ids);
323
324LWS_VISIBLE LWS_EXTERN void
325lws_dlo_contents(lws_dlo_t *parent, lws_dlo_dim_t *dim);
326
327LWS_VISIBLE LWS_EXTERN void
328lws_display_dlo_adjust_dims(lws_dlo_t *dlo, lws_dlo_dim_t *dim);
329
330/**
331 * lws_display_dl_init() - init display list object
332 *
333 * \param dl: Pointer to the display list
334 * \param ds: Lws display state to bind the list to
335 *
336 * Initializes the display list \p dl and binds it to the display state \p ds.
337 */
338LWS_VISIBLE LWS_EXTERN void
339lws_display_dl_init(lws_displaylist_t *dl, struct lws_display_state *ds);
340
341//#if defined(_DEBUG)
342LWS_VISIBLE LWS_EXTERN void
343lws_display_dl_dump(lws_displaylist_t *dl);
344//#endif
345
346/**
347 * lws_display_list_destroy() - destroys display list and objects on it
348 *
349 * \param dl: Pointer to the display list
350 *
351 * Destroys every DLO on the list.
352 */
353LWS_VISIBLE LWS_EXTERN void
354lws_display_list_destroy(lws_displaylist_t *dl);
355
356LWS_VISIBLE LWS_EXTERN void
357lws_display_dlo_destroy(lws_dlo_t **r);
358
359LWS_VISIBLE LWS_EXTERN int
360lws_display_dlo_add(lws_displaylist_t *dl, lws_dlo_t *dlo_parent, lws_dlo_t *dlo);
361
362LWS_VISIBLE LWS_EXTERN int
363lws_dlo_ensure_err_diff(lws_dlo_t *dlo);
364
365/*
366 * lws_display_list_render_line() - render a single raster line of the list
367 *
368 * \param rs: prepared render state object
369 *
370 * Allocates a line pair buffer into ds->line if necessary, and renders the
371 * current line (set by ds->curr) of the display list rasterization into it
372 */
373LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
374lws_display_list_render_line(lws_display_render_state_t *rs);
375
376LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
377lws_display_get_ids_boxes(lws_display_render_state_t *rs);
378
379/*
380 * rect
381 */
382
383LWS_VISIBLE LWS_EXTERN lws_dlo_rect_t *
384lws_display_dlo_rect_new(lws_displaylist_t *dl, lws_dlo_t *dlo_parent,
385 lws_box_t *box, const lws_fx_t *radii,
386 lws_display_colour_t dc);
387
388LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
389lws_display_render_rect(struct lws_display_render_state *rs);
390
391/*
392 * dlo text
393 */
394
395LWS_VISIBLE LWS_EXTERN lws_dlo_text_t *
396lws_display_dlo_text_new(lws_displaylist_t *dl, lws_dlo_t *dlo_parent,
397 lws_box_t *box, const lws_display_font_t *font);
398
399LWS_VISIBLE LWS_EXTERN int
400lws_display_dlo_text_update(lws_dlo_text_t *text, lws_display_colour_t dc,
401 lws_fx_t indent, const char *utf8, size_t text_len);
402
403LWS_VISIBLE LWS_EXTERN void
404lws_display_dlo_text_destroy(struct lws_dlo *dlo);
405
406/*
407 * PNG
408 */
409
410LWS_VISIBLE LWS_EXTERN lws_dlo_png_t *
411lws_display_dlo_png_new(lws_displaylist_t *dl, lws_dlo_t *dlo_parent,
412 lws_box_t *box);
413
414LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
415lws_display_render_png(struct lws_display_render_state *rs);
416
417LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
418lws_display_dlo_png_metadata_scan(lws_dlo_png_t *dp);
419
420LWS_VISIBLE LWS_EXTERN void
421lws_display_dlo_png_destroy(struct lws_dlo *dlo);
422
423/*
424 * JPEG
425 */
426
427LWS_VISIBLE LWS_EXTERN lws_dlo_jpeg_t *
428lws_display_dlo_jpeg_new(lws_displaylist_t *dl, lws_dlo_t *dlo_parent,
429 lws_box_t *box);
430
431LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
432lws_display_render_jpeg(struct lws_display_render_state *rs);
433
434LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
435lws_display_dlo_jpeg_metadata_scan(lws_dlo_jpeg_t *dj);
436
437LWS_VISIBLE LWS_EXTERN void
438lws_display_dlo_jpeg_destroy(struct lws_dlo *dlo);
439
440/*
441 * SS / dlo images
442 */
443
444struct lhp_ctx;
445
446typedef struct {
447 struct lws_context *cx;
448 lws_displaylist_t *dl;
449 lws_dlo_t *dlo_parent;
450 lws_box_t *box;
451 sul_cb_t on_rx;
452 lws_sorted_usec_list_t *on_rx_sul;
453 const char *url;
454 struct lhp_ctx *lhp;
455 lws_dlo_image_t *u;
456 int32_t window;
457
458 uint8_t type;
459} lws_dlo_ss_create_info_t;
460
461LWS_VISIBLE LWS_EXTERN int
462lws_dlo_ss_create(lws_dlo_ss_create_info_t *i, lws_dlo_t **pdlo);
463
464LWS_VISIBLE LWS_EXTERN int
465lws_dlo_ss_find(struct lws_context *cx, const char *url, lws_dlo_image_t *u);
466
467LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
468lhp_displaylist_layout(struct lhp_ctx *ctx, char reason);
469
470#define lws_dlo_image_width(_u) ((_u)->failed ? -1 : \
471 ((_u)->type == LWSDLOSS_TYPE_JPEG ? \
472 (int)lws_jpeg_get_width((_u)->u.dlo_jpeg->j) : \
473 (int)lws_upng_get_width((_u)->u.dlo_png->png)))
474#define lws_dlo_image_height(_u) ((_u)->failed ? -1 : \
475 ((_u)->type == LWSDLOSS_TYPE_JPEG ? \
476 (int)lws_jpeg_get_height((_u)->u.dlo_jpeg->j) : \
477 (int)lws_upng_get_height((_u)->u.dlo_png->png)))
478
479#define lws_dlo_image_metadata_scan(_u) ((_u)->failed ? LWS_SRET_FATAL : \
480 ((_u)->type == LWSDLOSS_TYPE_JPEG ? \
481 lws_display_dlo_jpeg_metadata_scan((_u)->u.dlo_jpeg) : \
482 lws_display_dlo_png_metadata_scan((_u)->u.dlo_png)))
483
484/*
485 * Font registry
486 *
487 * Register fonts (currently, psfu) to the lws_context, and select the closest
488 * matching. Used to pick fonts from whatever CSS information is available.
489 */
490
491LWS_VISIBLE LWS_EXTERN int
492lws_font_register(struct lws_context *cx, const uint8_t *data, size_t data_len);
493
494LWS_VISIBLE LWS_EXTERN const lws_display_font_t *
495lws_font_choose(struct lws_context *cx, const lws_font_choice_t *hints);
496
497LWS_VISIBLE LWS_EXTERN void
498lws_fonts_destroy(struct lws_context *cx);
499
500/*
501 * Static blob registry (built-in, name-accessible blobs)
502 */
503
504LWS_VISIBLE LWS_EXTERN lws_dlo_filesystem_t *
505lws_dlo_file_register(struct lws_context *cx, const lws_dlo_filesystem_t *f);
506
507/* only needed if f dynamically heap-allocated... doesn't free data; data
508 * is typically overallocated after the lws_dlo_filesystem_t and freed when
509 * that is freed by this. */
510
511LWS_VISIBLE LWS_EXTERN void
512lws_dlo_file_unregister(lws_dlo_filesystem_t **f);
513
514LWS_VISIBLE LWS_EXTERN void
515lws_dlo_file_unregister_by_name(struct lws_context *cx, const char *name);
516
517LWS_VISIBLE LWS_EXTERN const lws_dlo_filesystem_t *
518lws_dlo_file_choose(struct lws_context *cx, const char *name);
519
520LWS_VISIBLE LWS_EXTERN void
521lws_dlo_file_destroy(struct lws_context *cx);
522
523LWS_VISIBLE extern const struct lws_plat_file_ops lws_dlo_fops;
524#endif
525