From 25a529f440873f7ee22671e9c7f251c1a66f8a0d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Apr 2018 21:10:09 +0200 Subject: UI: add own icon rasterizer Use software drawing, cache to an image at the requested pixel size. --- source/blender/blenkernel/BKE_icons.h | 5 + source/blender/blenkernel/CMakeLists.txt | 1 + source/blender/blenkernel/intern/icons_rasterize.c | 131 +++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 source/blender/blenkernel/intern/icons_rasterize.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 47cac895645..fb40e5be281 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -71,6 +71,7 @@ struct Icon_Geom { typedef struct Icon Icon; +struct ImBuf; struct PreviewImage; struct ID; @@ -148,6 +149,10 @@ struct PreviewImage *BKE_previewimg_cached_thumbnail_read( void BKE_previewimg_cached_release(const char *name); void BKE_previewimg_cached_release_pointer(struct PreviewImage *prv); +struct ImBuf *BKE_icon_geom_rasterize( + const struct Icon_Geom *geom, + const unsigned int size_x, const unsigned int size_y); + #define ICON_RENDER_DEFAULT_HEIGHT 32 #endif /* __BKE_ICONS_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index d90831605b5..91915bf679a 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -116,6 +116,7 @@ set(SRC intern/gpencil.c intern/group.c intern/icons.c + intern/icons_rasterize.c intern/idcode.c intern/idprop.c intern/image.c diff --git a/source/blender/blenkernel/intern/icons_rasterize.c b/source/blender/blenkernel/intern/icons_rasterize.c new file mode 100644 index 00000000000..bb6ef38f8f7 --- /dev/null +++ b/source/blender/blenkernel/intern/icons_rasterize.c @@ -0,0 +1,131 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/blenkernel/intern/icons_rasterize.c + * \ingroup bke + */ +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_bitmap_draw_2d.h" +#include "BLI_math_geom.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BKE_icons.h" + +#include "BLI_strict_flags.h" + +struct UserRasterInfo { + int pt[3][2]; + const uint *color; + /* only for smooth shading */ + struct { + float pt_fl[3][2]; + uint color_u[3][4]; + } smooth; + int rect_size[2]; + uint *rect; +}; + +static void tri_fill_flat(int x, int x_end, int y, void *user_data) +{ + struct UserRasterInfo *data = user_data; + uint *p = &data->rect[(y * data->rect_size[1]) + x]; + uint col = data->color[0]; + while (x++ != x_end) { + *p++ = col; + } +} + +static void tri_fill_smooth(int x, int x_end, int y, void *user_data) +{ + struct UserRasterInfo *data = user_data; + uint *p = &data->rect[(y * data->rect_size[1]) + x]; + float pt_step_fl[2] = {(float)x, (float)y}; + while (x++ != x_end) { + float w[3]; + barycentric_weights_v2_clamped(UNPACK3(data->smooth.pt_fl), pt_step_fl, w); + + uint col_u[4] = {0, 0, 0, 0}; + for (uint corner = 0; corner < 3; corner++) { + for (uint chan = 0; chan < 4; chan++) { + col_u[chan] += data->smooth.color_u[corner][chan] * (uint)(w[corner] * 255.0f); + } + } + union { + uint as_u32; + uchar as_bytes[4]; + } col; + col.as_bytes[0] = (uchar)(col_u[0] / 255); + col.as_bytes[1] = (uchar)(col_u[1] / 255); + col.as_bytes[2] = (uchar)(col_u[2] / 255); + col.as_bytes[3] = (uchar)(col_u[3] / 255); + *p++ = col.as_u32; + + pt_step_fl[0] += 1.0f; + } +} + +ImBuf *BKE_icon_geom_rasterize( + const struct Icon_Geom *geom, + const unsigned int size_x, const unsigned int size_y) +{ + const int coords_len = geom->coords_len; + + const uchar (*pos)[2] = geom->coords; + const uint *col = (void *)geom->colors; + + /* TODO(campbell): Currently rasterizes to fixed size, then scales. + * Should rasterize to double size for eg instead. */ + const int rect_size[2] = {256, 256}; + + ImBuf *ibuf = IMB_allocImBuf((uint)rect_size[0], (uint)rect_size[1], 32, IB_rect); + + struct UserRasterInfo data; + + data.rect_size[0] = rect_size[0]; + data.rect_size[1] = rect_size[1]; + + data.rect = ibuf->rect; + + for (int t = 0; t < coords_len; t += 1, pos += 3, col += 3) { + ARRAY_SET_ITEMS(data.pt[0], UNPACK2(pos[0])); + ARRAY_SET_ITEMS(data.pt[1], UNPACK2(pos[1])); + ARRAY_SET_ITEMS(data.pt[2], UNPACK2(pos[2])); + data.color = col; + if ((col[0] == col[1]) && (col[0] == col[2])) { + BLI_bitmap_draw_2d_tri_v2i(UNPACK3(data.pt), tri_fill_flat, &data); + } + else { + ARRAY_SET_ITEMS(data.smooth.pt_fl[0], UNPACK2_EX((float), data.pt[0], )); + ARRAY_SET_ITEMS(data.smooth.pt_fl[1], UNPACK2_EX((float), data.pt[1], )); + ARRAY_SET_ITEMS(data.smooth.pt_fl[2], UNPACK2_EX((float), data.pt[2], )); + ARRAY_SET_ITEMS(data.smooth.color_u[0], UNPACK4_EX((uint), ((uchar *)(col + 0)), )); + ARRAY_SET_ITEMS(data.smooth.color_u[1], UNPACK4_EX((uint), ((uchar *)(col + 1)), )); + ARRAY_SET_ITEMS(data.smooth.color_u[2], UNPACK4_EX((uint), ((uchar *)(col + 2)), )); + BLI_bitmap_draw_2d_tri_v2i(UNPACK3(data.pt), tri_fill_smooth, &data); + } + } + IMB_scaleImBuf(ibuf, size_x, size_y); + return ibuf; +} -- cgit v1.2.3