diff options
-rw-r--r-- | source/blender/blenloader/BLO_readfile.h | 3 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readblenentry.c | 118 | ||||
-rw-r--r-- | source/blender/imbuf/intern/thumbs_blend.c | 42 |
3 files changed, 103 insertions, 60 deletions
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index dbdb181281a..4b7f29dd7dc 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -172,6 +172,9 @@ struct LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, int *r_tot_info_items); struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev); +struct PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh, + int ofblocktype, + const char *name); struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh); void BLO_blendhandle_close(BlendHandle *bh); diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 44a26b9bf85..f67ff0f7ac7 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -217,6 +217,96 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, } /** + * Read the preview rects and store in `result`. + * + * `bhead` should point to the block that sourced the `preview_from_file` + * parameter. + * `bhead` parameter is consumed. The correct bhead pointing to the next bhead in the file after + * the preview rects is returned by this function. + * \param fd: The filedata to read the data from. + * \param bhead: should point to the block that sourced the `preview_from_file parameter`. + * bhead is consumed. the new bhead is returned by this function. + * \param result: the Preview Image where the preview rect will be stored. + * \param preview_from_file: The read PreviewImage where the bhead points to. The rects of this + * \return PreviewImage or NULL when no preview Images have been found. Caller owns the returned + */ +static BHead *blo_blendhandle_read_preview_rects(FileData *fd, + BHead *bhead, + PreviewImage *result, + const PreviewImage *preview_from_file) +{ + for (int preview_index = 0; preview_index < NUM_ICON_SIZES; preview_index++) { + if (preview_from_file->rect[preview_index] && preview_from_file->w[preview_index] && + preview_from_file->h[preview_index]) { + bhead = blo_bhead_next(fd, bhead); + BLI_assert((preview_from_file->w[preview_index] * preview_from_file->h[preview_index] * + sizeof(uint)) == bhead->len); + result->rect[preview_index] = BLO_library_read_struct(fd, bhead, "PreviewImage Icon Rect"); + } + else { + /* This should not be needed, but can happen in 'broken' .blend files, + * better handle this gracefully than crashing. */ + BLI_assert(preview_from_file->rect[preview_index] == NULL && + preview_from_file->w[preview_index] == 0 && + preview_from_file->h[preview_index] == 0); + result->rect[preview_index] = NULL; + result->w[preview_index] = result->h[preview_index] = 0; + } + BKE_previewimg_finish(result, preview_index); + } + + return bhead; +} + +/** + * Get the PreviewImage of a single data block in a file. + * (e.g. all the scene previews in a file). + * + * \param bh: The blendhandle to access. + * \param ofblocktype: The type of names to get. + * \param name: Name of the block without the ID_ prefix, to read the preview image from. + * \return PreviewImage or NULL when no preview Images have been found. Caller owns the returned + */ +PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh, + int ofblocktype, + const char *name) +{ + FileData *fd = (FileData *)bh; + bool looking = false; + const int sdna_preview_image = DNA_struct_find_nr(fd->filesdna, "PreviewImage"); + + for (BHead *bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) { + if (bhead->code == DATA) { + if (looking && bhead->SDNAnr == sdna_preview_image) { + PreviewImage *preview_from_file = BLO_library_read_struct(fd, bhead, "PreviewImage"); + + if (preview_from_file == NULL) { + break; + } + + PreviewImage *result = MEM_dupallocN(preview_from_file); + bhead = blo_blendhandle_read_preview_rects(fd, bhead, result, preview_from_file); + MEM_freeN(preview_from_file); + return result; + } + } + else if (looking || bhead->code == ENDB) { + /* We were looking for a preview image, but didn't find any belonging to block. So it doesn't + * exist. */ + break; + } + else if (bhead->code == ofblocktype) { + const char *idname = blo_bhead_id_name(fd, bhead); + if (STREQ(&idname[2], name)) { + looking = true; + } + } + } + + return NULL; +} + +/** * Gets the previews of all the data-blocks in a file of a certain type * (e.g. all the scene previews in a file). * @@ -264,33 +354,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_ if (prv) { memcpy(new_prv, prv, sizeof(PreviewImage)); - if (prv->rect[0] && prv->w[0] && prv->h[0]) { - bhead = blo_bhead_next(fd, bhead); - BLI_assert((new_prv->w[0] * new_prv->h[0] * sizeof(uint)) == bhead->len); - new_prv->rect[0] = BLO_library_read_struct(fd, bhead, "PreviewImage Icon Rect"); - } - else { - /* This should not be needed, but can happen in 'broken' .blend files, - * better handle this gracefully than crashing. */ - BLI_assert(prv->rect[0] == NULL && prv->w[0] == 0 && prv->h[0] == 0); - new_prv->rect[0] = NULL; - new_prv->w[0] = new_prv->h[0] = 0; - } - BKE_previewimg_finish(new_prv, 0); - - if (prv->rect[1] && prv->w[1] && prv->h[1]) { - bhead = blo_bhead_next(fd, bhead); - BLI_assert((new_prv->w[1] * new_prv->h[1] * sizeof(uint)) == bhead->len); - new_prv->rect[1] = BLO_library_read_struct(fd, bhead, "PreviewImage Image Rect"); - } - else { - /* This should not be needed, but can happen in 'broken' .blend files, - * better handle this gracefully than crashing. */ - BLI_assert(prv->rect[1] == NULL && prv->w[1] == 0 && prv->h[1] == 0); - new_prv->rect[1] = NULL; - new_prv->w[1] = new_prv->h[1] = 0; - } - BKE_previewimg_finish(new_prv, 1); + bhead = blo_blendhandle_read_preview_rects(fd, bhead, new_prv, prv); MEM_freeN(prv); } } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index 878aa44f0d9..085620cb785 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -41,53 +41,29 @@ #include "MEM_guardedalloc.h" +/* NOTE: we should handle all previews for a same group at once, would avoid reopening + * `.blend` file for each and every ID. However, this adds some complexity, + * so keep it for later. */ static ImBuf *imb_thumb_load_from_blend_id(const char *blen_path, const char *blen_group, const char *blen_id) { ImBuf *ima = NULL; - LinkNode *ln, *names, *lp, *previews = NULL; BlendFileReadReport bf_reports = {.reports = NULL}; - struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, &bf_reports); - int idcode = BKE_idtype_idcode_from_name(blen_group); - int i, nprevs, nnames; + struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, &bf_reports); if (libfiledata == NULL) { return NULL; } - /* NOTE: we should handle all previews for a same group at once, would avoid reopening - * `.blend` file for each and every ID. However, this adds some complexity, - * so keep it for later. */ - names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, false, &nnames); - previews = BLO_blendhandle_get_previews(libfiledata, idcode, &nprevs); - + int idcode = BKE_idtype_idcode_from_name(blen_group); + PreviewImage *preview = BLO_blendhandle_get_preview_for_id(libfiledata, idcode, blen_id); BLO_blendhandle_close(libfiledata); - if (!previews || (nnames != nprevs)) { - if (previews != 0) { - /* No previews at all is not a bug! */ - printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs); - } - BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_freeN(names); - return NULL; + if (preview) { + ima = BKE_previewimg_to_imbuf(preview, ICON_SIZE_PREVIEW); + BKE_previewimg_freefunc(preview); } - - for (i = 0, ln = names, lp = previews; i < nnames; i++, ln = ln->next, lp = lp->next) { - const char *blockname = ln->link; - PreviewImage *img = lp->link; - - if (STREQ(blockname, blen_id)) { - if (img) { - ima = BKE_previewimg_to_imbuf(img, ICON_SIZE_PREVIEW); - } - break; - } - } - - BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_freeN(names); return ima; } |