diff --git a/changelog b/changelog index e1f483063..ec8ed0d16 100644 --- a/changelog +++ b/changelog @@ -1,6 +1,17 @@ Changelog --------- +v4.4.0 +====== + + - API CHANGE: VFS open() has an extra file_ops pointer at the beginning. + The other args shift along one and are otherwise unchanged. The new + file_ops is the active file_ops the callback belongs to, the original + file_ops that's the second arg now remains the platform file_ops ptr. If you + don't define your own VFS implementation, you don't need to care. + + + v4.3.0 ====== diff --git a/include/libwebsockets/lws-dlo.h b/include/libwebsockets/lws-dlo.h index fae02e87d..1de3415c1 100644 --- a/include/libwebsockets/lws-dlo.h +++ b/include/libwebsockets/lws-dlo.h @@ -73,6 +73,23 @@ typedef lws_font_glyph_t * (*lws_dlo_image_glyph_t)( uint32_t unicode, char attach); typedef void (*lws_dlo_destroy_t)(struct lws_dlo *dlo); +typedef struct lws_display_id { + lws_dll2_t list; + + char id[16]; + lws_box_t box; /* taken from DLO after layout */ + + void *priv_user; + void *priv_driver; + + char exists; + char iframe; /* 1 = render html as if partial + * is the origin, otherwise + * render html with surface + * (0,0) as origin and rs->box + * is a viewport on to that */ +} lws_display_id_t; + /* * Common dlo object that joins the display list, composed into a subclass * object like lws_dlo_rect_t etc @@ -88,6 +105,8 @@ typedef struct lws_dlo { lws_dlo_destroy_t _destroy; /* dlo-type specific cb */ lws_dlo_renderer_t render; /* dlo-type specific cb */ + lws_display_id_t *id; /* only valid until ids destroyed */ + lws_box_t box; lws_display_colour_t dc; @@ -247,6 +266,8 @@ typedef struct lws_display_render_state { lws_sorted_usec_list_t sul; /* return to event loop statefully */ lws_display_state_t *lds; /* optional, if using lws_display */ + lws_dll2_owner_t ids; + const struct lws_surface_info *ic; /* display dimensions, palette */ lws_display_render_stack_t st[12]; /* DLO child stack */ @@ -255,12 +276,27 @@ typedef struct lws_display_render_state { uint8_t *line; /* Y or RGB line comp buffer */ lws_displaylist_t displaylist; - lws_box_t box; + lws_display_scalar curr; + lws_display_scalar lowest_id_y; + char html; + } lws_display_render_state_t; +LWS_VISIBLE LWS_EXTERN void +lws_display_render_free_ids(lws_display_render_state_t *rs); + +LWS_VISIBLE LWS_EXTERN lws_display_id_t * +lws_display_render_add_id(lws_display_render_state_t *rs, const char *id, void *priv); + +LWS_VISIBLE LWS_EXTERN lws_display_id_t * +lws_display_render_get_id(lws_display_render_state_t *rs, const char *id); + +LWS_VISIBLE LWS_EXTERN void +lws_display_render_dump_ids(lws_dll2_owner_t *ids); + /** * lws_display_dl_init() - init display list object * @@ -272,10 +308,10 @@ typedef struct lws_display_render_state { LWS_VISIBLE LWS_EXTERN void lws_display_dl_init(lws_displaylist_t *dl, struct lws_display_state *ds); -#if defined(_DEBUG) +//#if defined(_DEBUG) LWS_VISIBLE LWS_EXTERN void lws_display_dl_dump(lws_displaylist_t *dl); -#endif +//#endif /** * lws_display_list_destroy() - destroys display list and objects on it @@ -307,6 +343,9 @@ lws_dlo_ensure_err_diff(lws_dlo_t *dlo); LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t lws_display_list_render_line(lws_display_render_state_t *rs); +LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t +lws_display_get_ids_boxes(lws_display_render_state_t *rs); + /* * rect */ @@ -396,7 +435,7 @@ LWS_VISIBLE LWS_EXTERN int lws_dlo_ss_find(struct lws_context *cx, const char *url, lws_dlo_image_t *u); LWS_VISIBLE LWS_EXTERN signed char -lhp_dl_render(lhp_ctx_t *ctx, char reason); +lhp_displaylist_layout(lhp_ctx_t *ctx, char reason); #define lws_dlo_image_width(_u) ((_u)->failed ? -1 : \ ((_u)->type == LWSDLOSS_TYPE_JPEG ? \ @@ -435,9 +474,17 @@ lws_fonts_destroy(struct lws_context *cx); LWS_VISIBLE LWS_EXTERN int lws_dlo_file_register(struct lws_context *cx, const lws_dlo_filesystem_t *f); +/* only needed if f dynamically heap-allocated... doesn't free data; data + * is typically overallocated after the lws_dlo_filesystem_t and freed when + * that is freed by this. */ + +LWS_VISIBLE LWS_EXTERN void +lws_dlo_file_unregister(lws_dlo_filesystem_t **f); + LWS_VISIBLE LWS_EXTERN const lws_dlo_filesystem_t * lws_dlo_file_choose(struct lws_context *cx, const char *name); LWS_VISIBLE LWS_EXTERN void lws_dlo_file_destroy(struct lws_context *cx); +LWS_VISIBLE extern const struct lws_plat_file_ops lws_dlo_fops; diff --git a/lib/core/context.c b/lib/core/context.c index 4ccff9105..84a5e337a 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -807,12 +807,6 @@ lws_create_context(const struct lws_context_creation_info *info) #endif #endif -#if defined(LWS_WITH_SERVER) - context->lcg[LWSLCG_WSI_SSP_SINK].tag_prefix = "SSsink"; - context->lcg[LWSLCG_WSI_SSP_SOURCE].tag_prefix = "SSsrc"; -#endif - - #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) /* directly use the user-provided policy object list */ context->pss_policies = info->pss_policies; diff --git a/lib/misc/dlo/dlo.c b/lib/misc/dlo/dlo.c index 07c7069e3..6d113fdfc 100644 --- a/lib/misc/dlo/dlo.c +++ b/lib/misc/dlo/dlo.c @@ -55,6 +55,7 @@ lws_surface_set_px(const lws_surface_info_t *ic, uint8_t *line, int x, { unsigned int alpha, ialpha; lws_display_colour_t oc; + lws_display_colour_t y; uint8_t rgb[3]; if (x < 0 || x >= ic->wh_px[0].whole) @@ -72,7 +73,9 @@ lws_surface_set_px(const lws_surface_info_t *ic, uint8_t *line, int x, alpha = LWSDC_ALPHA(*c); ialpha = 255 - alpha; - line[x] = (uint8_t)(((LWSDC_R(*c) * alpha) / 255) + + y = RGB_TO_Y(LWSDC_R(*c), LWSDC_G(*c), LWSDC_B(*c)); + + line[x] = (uint8_t)(((y * alpha) / 255) + ((LWSDC_R(oc) * ialpha) / 255)); return; } @@ -97,7 +100,7 @@ lws_surface_set_px(const lws_surface_info_t *ic, uint8_t *line, int x, } -#if defined(_DEBUG) +//#if defined(_DEBUG) void lws_display_dl_dump(lws_displaylist_t *dl) { @@ -142,8 +145,9 @@ lws_display_dl_dump(lws_displaylist_t *dl) lws_snprintf(dt, sizeof(dt), "rect: RGBA 0x%08X", (unsigned int)dlo->dc); if (dlo->_destroy == lws_display_dlo_text_destroy) { lws_dlo_text_t *text = lws_container_of(dlo, lws_dlo_text_t, dlo); - lws_snprintf(dt, sizeof(dt), "text: RGBA 0x%08X, chars: %u, %s", - (unsigned int)dlo->dc, (unsigned int)text->text_len, text->text); + lws_snprintf(dt, sizeof(dt), "text: RGBA 0x%08X, chars: %u, %.*s", + (unsigned int)dlo->dc, (unsigned int)text->text_len, + (int)text->text_len, text->text ? text->text : "(empty)"); } else if (dlo->_destroy == lws_display_dlo_png_destroy) lws_snprintf(dt, sizeof(dt), "png"); @@ -182,7 +186,87 @@ lws_display_dl_dump(lws_displaylist_t *dl) st[sp].dlo = NULL; } } -#endif +//#endif + +/* + * Go through every DLO once, setting its id->box to the final layout for the + * related dlo, if any + */ + +lws_stateful_ret_t +lws_display_get_ids_boxes(lws_display_render_state_t *rs) +{ + lws_dll2_t *d; + + rs->lowest_id_y = 0; + + d = lws_dll2_get_head(&rs->displaylist.dl); + if (!d) + /* nothing in dlo */ + return LWS_SRET_OK; + + memset(&rs->st[0].co, 0, sizeof(rs->st[0].co)); + rs->st[0].dlo = lws_container_of(d, lws_dlo_t, list); + + while (rs->sp || rs->st[0].dlo) { + lws_dlo_t *dlo = rs->st[rs->sp].dlo; + lws_box_t co; + lws_fx_t t2; + + if (!dlo) { + rs->sp--; + continue; + } + + lws_fx_add(&co.x, &rs->st[rs->sp].co.x, &dlo->box.x); + lws_fx_add(&co.y, &rs->st[rs->sp].co.y, &dlo->box.y); + co.w = dlo->box.w; + co.h = dlo->box.h; + + lws_fx_add(&t2, &co.y, &dlo->box.h); + + if (dlo->id) { + lws_display_id_t *id = dlo->id; + + lwsl_debug("%s: set id box %s\n", __func__, id->id); + id->box = co; + dlo->id = NULL; /* decouple us */ + } + + if (co.y.whole + co.h.whole > rs->lowest_id_y) { + rs->lowest_id_y = (lws_display_scalar)(co.y.whole + co.h.whole); + if (rs->lowest_id_y > rs->ic->wh_px[1].whole) + rs->lowest_id_y = (lws_display_scalar)rs->ic->wh_px[1].whole; + } + + /* next sibling at this level if any */ + + d = dlo->list.next; + if (d) + rs->st[rs->sp].dlo = lws_container_of(d, + lws_dlo_t, list); + else + rs->st[rs->sp].dlo = NULL; + + /* go into any children */ + + if (dlo->children.head) { + if (rs->sp + 1 == LWS_ARRAY_SIZE(rs->st)) { + lwsl_err("%s: DLO stack overflow\n", + __func__); + return LWS_SRET_FATAL; + } + rs->st[++rs->sp].dlo = lws_container_of( + dlo->children.head, lws_dlo_t, list); + rs->st[rs->sp].co = co; + continue; + } + } + + lws_display_render_dump_ids(&rs->ids); + + return LWS_SRET_OK; +} lws_stateful_ret_t lws_display_list_render_line(lws_display_render_state_t *rs) @@ -324,7 +408,17 @@ lws_display_list_destroy(lws_displaylist_t *dl) int lws_dlo_file_register(struct lws_context *cx, const lws_dlo_filesystem_t *f) { - lws_dlo_filesystem_t *a = lws_malloc(sizeof(*a), __func__); + const lws_dlo_filesystem_t *b; + lws_dlo_filesystem_t *a; + + b = lws_dlo_file_choose(cx, f->name); + + if (b) { + lwsl_err("%s: dlo file %s already exists\n", __func__, b->name); + lws_dlo_file_unregister((lws_dlo_filesystem_t **)&b); + } + + a = lws_malloc(sizeof(*a), __func__); if (!a) return 1; @@ -335,6 +429,20 @@ lws_dlo_file_register(struct lws_context *cx, const lws_dlo_filesystem_t *f) return 0; } +/* + * Only needed with heap-alloc'd lws_dlo_filesystem_t + */ + +void +lws_dlo_file_unregister(lws_dlo_filesystem_t **f) +{ + if (!*f) + return; + + lws_dll2_remove(&(*f)->list); + lws_free_set_NULL(*f); +} + static int _lws_dlo_file_destroy(struct lws_dll2 *d, void *user) { @@ -363,3 +471,171 @@ lws_dlo_file_choose(struct lws_context *cx, const char *name) return NULL; } + +static int +lws_display_id_destroy(struct lws_dll2 *d, void *user) +{ + lws_display_id_t *id = lws_container_of(d, lws_display_id_t, list); + + lws_dll2_remove(&id->list); + lws_free(id); + return 0; +} + +void +lws_display_render_free_ids(lws_display_render_state_t *rs) +{ + lws_dll2_foreach_safe(&rs->ids, NULL, lws_display_id_destroy); +} + +lws_display_id_t * +lws_display_render_get_id(lws_display_render_state_t *rs, const char *_id) +{ + lws_start_foreach_dll(struct lws_dll2 *, d, lws_dll2_get_head(&rs->ids)) { + lws_display_id_t *id = lws_container_of(d, lws_display_id_t, list); + + if (!strcmp(_id, id->id)) + return id; + + } lws_end_foreach_dll(d); + + return NULL; +} + +lws_display_id_t * +lws_display_render_add_id(lws_display_render_state_t *rs, const char *_id, void *priv) +{ + lws_display_id_t *id; + + id = lws_display_render_get_id(rs, _id); + if (id) { + id->priv_user = priv; + return id; + } + + id = lws_zalloc(sizeof(*id), __func__); + + if (id) { + lws_strncpy(id->id, _id, sizeof(id->id)); + id->priv_user = priv; + lws_dll2_add_tail(&id->list, &rs->ids); + } + + return id; +} + +void +lws_display_render_dump_ids(lws_dll2_owner_t *ids) +{ + lws_start_foreach_dll(struct lws_dll2 *, d, lws_dll2_get_head(ids)) { + lws_display_id_t *id = lws_container_of(d, lws_display_id_t, list); + + if (!id->exists) + lwsl_notice(" id: '%s' (not present)\n", id->id); + else + lwsl_notice(" id: '%s', (%d,%d), %dx%d\n", id->id, + id->box.x.whole, id->box.y.whole, + id->box.w.whole, id->box.h.whole); + } lws_end_foreach_dll(d); +} + +#if defined (LWS_WITH_FILE_OPS) + +int +dlo_filesystem_fops_close(lws_fop_fd_t *fop_fd) +{ + lws_free_set_NULL(*fop_fd); + return 0; +} + +lws_fileofs_t +dlo_filesystem_fops_seek_cur(lws_fop_fd_t fop_fd, + lws_fileofs_t pos) +{ + if (pos < 0) + fop_fd->pos = 0; + else + if (pos >= (long long)fop_fd->len) + fop_fd->pos = fop_fd->len; + else + fop_fd->pos = (lws_filepos_t)pos; + + return (lws_fileofs_t)fop_fd->pos; +} + +int +dlo_filesystem_fops_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len) +{ + *amount = 0; + + return -1; +} + +int +dlo_filesystem_fops_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len) +{ + const uint8_t *p = (uint8_t *)fop_fd->filesystem_priv; + lws_filepos_t amt = *amount; + + *amount = 0; + if (fop_fd->len <= fop_fd->pos) + return 0; + + if (amt > fop_fd->len - fop_fd->pos) + amt = fop_fd->len - fop_fd->pos; + + if (amt > len) + amt = len; + + memcpy(buf, p + fop_fd->pos, (size_t)amt); + fop_fd->pos += amt; + + *amount = amt; + + return 0; +} + +lws_fop_fd_t +lws_dlo_filesystem_fops_open(const struct lws_plat_file_ops *fops_own, + const struct lws_plat_file_ops *fops, + const char *vfs_path, const char *vpath, + lws_fop_flags_t *flags) +{ + const lws_dlo_filesystem_t *f = NULL; + lws_fop_fd_t fop_fd; + + // lwsl_err("%s: %s\n", __func__, vpath); + + f = lws_dlo_file_choose(fops->cx, vpath); + if (f) { + /* we will handle it then */ + fop_fd = lws_zalloc(sizeof(*fop_fd), __func__); + if (!fop_fd) + return NULL; + + fop_fd->fops = fops_own; + fop_fd->filesystem_priv = (void *)f->data; + fop_fd->pos = 0; + fop_fd->len = f->len; + + // lwsl_notice("%s: Opened %s\n", __func__, vpath); + + return fop_fd; + } else + lwsl_err("%s: failed to open %s\n", __func__, vpath); + + return NULL; +} + +const struct lws_plat_file_ops lws_dlo_fops = { + .LWS_FOP_OPEN = lws_dlo_filesystem_fops_open, + .LWS_FOP_CLOSE = dlo_filesystem_fops_close, + .LWS_FOP_SEEK_CUR = dlo_filesystem_fops_seek_cur, + .LWS_FOP_READ = dlo_filesystem_fops_read, + .LWS_FOP_WRITE = dlo_filesystem_fops_write, + .fi = { { "dlofs/", 6 } }, +}; + +#endif diff --git a/test-apps/test-server.c b/test-apps/test-server.c index 20de3ee69..48963a7f3 100644 --- a/test-apps/test-server.c +++ b/test-apps/test-server.c @@ -203,14 +203,15 @@ static struct lws_protocols protocols[] = { * compressed files without decompressing the whole archive) */ static lws_fop_fd_t -test_server_fops_open(const struct lws_plat_file_ops *fops, +test_server_fops_open(const struct lws_plat_file_ops *this_fops, + const struct lws_plat_file_ops *fops, const char *vfs_path, const char *vpath, lws_fop_flags_t *flags) { lws_fop_fd_t fop_fd; /* call through to original platform implementation */ - fop_fd = fops_plat.open(fops, vfs_path, vpath, flags); + fop_fd = fops_plat.open(fops, fops, vfs_path, vpath, flags); if (fop_fd) lwsl_info("%s: opening %s, ret %p, len %lu\n", __func__,