Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen Bakker <j.bakker@atmind.nl>2019-05-09 16:53:44 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-05-09 20:55:10 +0300
commit5f7eebda23b844e932294b1ecaced46b5c75dde0 (patch)
tree0cdb5d6955d812a9ae5a64e8d48e8de76dffb4ee /source/blender/editors/interface/interface_icons.c
parent9b924d73da90526f5caf31b01dfd34156337f075 (diff)
Themes: add setting to draw border around icons, use for Blender Light
Monochrome colored icons don't work well on a dark background, so now we can add a border around them. Note that most icons in the interface will remain without a border, just the outliner and properties editor navigation have colored icons and those will get a border. Other icons continue to be drawn in the text colored without a border. Differential Revision: https://developer.blender.org/D4787
Diffstat (limited to 'source/blender/editors/interface/interface_icons.c')
-rw-r--r--source/blender/editors/interface/interface_icons.c418
1 files changed, 291 insertions, 127 deletions
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 4cfc942d3f5..7fdaa99c464 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
#include "BLI_math_vector.h"
+#include "BLI_math_color_blend.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -83,6 +84,7 @@
# define ICON_GRID_COLS 26
# define ICON_GRID_ROWS 30
+# define ICON_MONO_BORDER_OUTSET 2
# define ICON_GRID_MARGIN 10
# define ICON_GRID_W 32
# define ICON_GRID_H 32
@@ -138,7 +140,8 @@ typedef struct DrawInfo {
} DrawInfo;
typedef struct IconTexture {
- GLuint id;
+ GLuint id[2];
+ int num_textures;
int w;
int h;
float invw;
@@ -154,7 +157,7 @@ typedef struct IconType {
/* static here to cache results of icon directory scan, so it's not
* scanning the filesystem each time the menu is drawn */
static struct ListBase iconfilelist = {NULL, NULL};
-static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
+static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f};
#ifndef WITH_HEADLESS
@@ -714,38 +717,146 @@ static void icon_verify_datatoc(IconImage *iimg)
}
}
-static void init_internal_icons(void)
+static ImBuf *create_mono_icon_with_border(ImBuf *buf,
+ int resolution_divider,
+ float border_intensity)
{
- // bTheme *btheme = UI_GetTheme();
- ImBuf *b16buf = NULL, *b32buf = NULL;
- int x, y;
+ ImBuf *result = IMB_dupImBuf(buf);
+ const float border_sharpness = 16.0 / (resolution_divider * resolution_divider);
-# if 0 // temp disabled
- if ((btheme != NULL) && btheme->tui.iconfile[0]) {
- char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
- char iconfilestr[FILE_MAX];
+ float blurred_alpha_buffer[(ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) *
+ (ICON_GRID_H + 2 * ICON_MONO_BORDER_OUTSET)];
+ const int icon_width = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
+ const int icon_height = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
- if (icondir) {
- BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+ for (int y = 0; y < ICON_GRID_ROWS; y++) {
+ for (int x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (icontype.type != ICON_TYPE_MONO_TEXTURE) {
+ continue;
+ }
- /* if the image is missing bbuf will just be NULL */
- bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
+ int sx = x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
+ int sy = y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
+ sx = sx / resolution_divider;
+ sy = sy / resolution_divider;
+
+ /* blur the alpha channel and store it in blurred_alpha_buffer */
+ int blur_size = 2 / resolution_divider;
+ for (int bx = 0; bx < icon_width; bx++) {
+ const int asx = MAX2(bx - blur_size, 0);
+ const int aex = MIN2(bx + blur_size + 1, icon_width);
+ for (int by = 0; by < icon_height; by++) {
+ const int asy = MAX2(by - blur_size, 0);
+ const int aey = MIN2(by + blur_size + 1, icon_height);
+
+ // blur alpha channel
+ const int write_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
+ float alpha_accum = 0.0;
+ unsigned int alpha_samples = 0;
+ for (int ax = asx; ax < aex; ax++) {
+ for (int ay = asy; ay < aey; ay++) {
+ const int offset_read = (sy + ay) * buf->x + (sx + ax);
+ unsigned int color_read = buf->rect[offset_read];
+ const float alpha_read = ((color_read & 0xff000000) >> 24) / 255.0;
+ alpha_accum += alpha_read;
+ alpha_samples += 1;
+ }
+ }
+ blurred_alpha_buffer[write_offset] = alpha_accum / alpha_samples;
+ }
+ }
- if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
- printf(
- "\n***WARNING***\n"
- "Icons file '%s' too small.\n"
- "Using built-in Icons instead\n",
- iconfilestr);
- IMB_freeImBuf(bbuf);
- bbuf = NULL;
+ /* apply blurred alpha */
+ for (int bx = 0; bx < icon_width; bx++) {
+ for (int by = 0; by < icon_height; by++) {
+ const int blurred_alpha_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
+ const int offset_write = (sy + by) * buf->x + (sx + bx);
+ const float blurred_alpha = blurred_alpha_buffer[blurred_alpha_offset];
+ float border_srgb[4] = {
+ 0, 0, 0, MIN2(1.0, blurred_alpha * border_sharpness) * border_intensity};
+
+ const unsigned int color_read = buf->rect[offset_write];
+ const unsigned char *orig_color = (unsigned char *)&color_read;
+
+ float border_rgba[4];
+ float orig_rgba[4];
+ float dest_rgba[4];
+ float dest_srgb[4];
+
+ srgb_to_linearrgb_v4(border_rgba, border_srgb);
+ srgb_to_linearrgb_uchar4(orig_rgba, orig_color);
+ blend_color_interpolate_float(dest_rgba, orig_rgba, border_rgba, 1.0 - orig_rgba[3]);
+ linearrgb_to_srgb_v4(dest_srgb, dest_rgba);
+
+ unsigned int alpha_mask = ((unsigned int)(dest_srgb[3] * 255)) << 24;
+ unsigned int cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask;
+ result->rect[offset_write] = cpack;
+ }
}
}
- else {
- printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ return result;
+}
+
+/* Generate the mipmap levels for the icon textures
+ * During creation the source16 ImBuf will be freed to reduce memory overhead
+ * A new ImBuf will be returned that needs is owned by the caller.
+ *
+ * FIXME: Mipmap levels are generated until the width of the image is 1, which
+ * are too many levels than that are needed.*/
+static ImBuf *create_mono_icon_mipmaps(ImBuf *source32, ImBuf *source16, int level)
+{
+ if (level == 0) {
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ source32->x,
+ source32->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ source32->rect);
+ return create_mono_icon_mipmaps(source32, source16, level + 1);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ source16->x,
+ source16->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ source16->rect);
+ if (source16->x > 1) {
+ ImBuf *nbuf = IMB_onehalf(source16);
+ IMB_freeImBuf(source16);
+ source16 = create_mono_icon_mipmaps(source32, nbuf, level + 1);
}
+ return source16;
}
-# endif
+}
+
+static void free_icons_textures(void)
+{
+ if (icongltex.num_textures > 0) {
+ glDeleteTextures(icongltex.num_textures, icongltex.id);
+ icongltex.id[0] = 0;
+ icongltex.id[1] = 0;
+ icongltex.num_textures = 0;
+ }
+}
+
+/* Reload the textures for internal icons.
+ * This function will release the previous textures. */
+void UI_icons_reload_internal_textures(void)
+{
+ bTheme *btheme = UI_GetTheme();
+ ImBuf *b16buf = NULL, *b32buf = NULL, *b16buf_border = NULL, *b32buf_border = NULL;
+ const float icon_border_intensity = btheme->tui.icon_border_intensity;
+ bool need_icons_with_border = icon_border_intensity > 0.0f;
+
if (b16buf == NULL) {
b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
datatoc_blender_icons16_png_size,
@@ -754,6 +865,10 @@ static void init_internal_icons(void)
"<blender icons>");
}
if (b16buf) {
+ if (need_icons_with_border) {
+ b16buf_border = create_mono_icon_with_border(b16buf, 2, icon_border_intensity);
+ IMB_premultiply_alpha(b16buf_border);
+ }
IMB_premultiply_alpha(b16buf);
}
@@ -765,88 +880,97 @@ static void init_internal_icons(void)
"<blender icons>");
}
if (b32buf) {
+ if (need_icons_with_border) {
+ b32buf_border = create_mono_icon_with_border(b32buf, 1, icon_border_intensity);
+ IMB_premultiply_alpha(b32buf_border);
+ }
IMB_premultiply_alpha(b32buf);
}
if (b16buf && b32buf) {
/* Free existing texture if any. */
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
+ free_icons_textures();
/* Allocate OpenGL texture. */
- glGenTextures(1, &icongltex.id);
+ icongltex.num_textures = need_icons_with_border ? 2 : 1;
+ glGenTextures(icongltex.num_textures, icongltex.id);
if (icongltex.id) {
- int level = 2;
-
icongltex.w = b32buf->x;
icongltex.h = b32buf->y;
icongltex.invw = 1.0f / b32buf->x;
icongltex.invh = 1.0f / b32buf->y;
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
-
- glTexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA8,
- b32buf->x,
- b32buf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- b32buf->rect);
- glTexImage2D(GL_TEXTURE_2D,
- 1,
- GL_RGBA8,
- b16buf->x,
- b16buf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- b16buf->rect);
-
- while (b16buf->x > 1) {
- ImBuf *nbuf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D,
- level,
- GL_RGBA8,
- nbuf->x,
- nbuf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- nbuf->rect);
- level++;
- IMB_freeImBuf(b16buf);
- b16buf = nbuf;
- }
-
+ glBindTexture(GL_TEXTURE_2D, icongltex.id[0]);
+ b16buf = create_mono_icon_mipmaps(b32buf, b16buf, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ if (need_icons_with_border && icongltex.id[1]) {
+ glBindTexture(GL_TEXTURE_2D, icongltex.id[1]);
+ b16buf_border = create_mono_icon_mipmaps(b32buf_border, b16buf_border, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
+ }
- /* Define icons. */
- for (y = 0; y < ICON_GRID_ROWS; y++) {
- /* Row W has monochrome icons. */
- for (x = 0; x < ICON_GRID_COLS; x++) {
- IconType icontype = icontypes[y * ICON_GRID_COLS + x];
- if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
- continue;
- }
+ IMB_freeImBuf(b16buf);
+ IMB_freeImBuf(b32buf);
+ IMB_freeImBuf(b16buf_border);
+ IMB_freeImBuf(b32buf_border);
+}
+
+static void init_internal_icons(void)
+{
+ int x, y;
+
+# if 0 // temp disabled
+ if ((btheme != NULL) && btheme->tui.iconfile[0]) {
+ char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
+ char iconfilestr[FILE_MAX];
+
+ if (icondir) {
+ BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+
+ /* if the image is missing bbuf will just be NULL */
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
- def_internal_icon(b32buf,
- BIFICONID_FIRST + y * ICON_GRID_COLS + x,
- x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- ICON_GRID_W,
- icontype.type,
- icontype.theme_color);
+ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
+ printf(
+ "\n***WARNING***\n"
+ "Icons file '%s' too small.\n"
+ "Using built-in Icons instead\n",
+ iconfilestr);
+ IMB_freeImBuf(bbuf);
+ bbuf = NULL;
}
}
+ else {
+ printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ }
+# endif
+
+ /* Define icons. */
+ for (y = 0; y < ICON_GRID_ROWS; y++) {
+ /* Row W has monochrome icons. */
+ for (x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
+ continue;
+ }
+
+ def_internal_icon(NULL,
+ BIFICONID_FIRST + y * ICON_GRID_COLS + x,
+ x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ ICON_GRID_W,
+ icontype.type,
+ icontype.theme_color);
+ }
}
def_internal_vicon(ICON_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
@@ -883,9 +1007,6 @@ static void init_internal_icons(void)
def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
-
- IMB_freeImBuf(b16buf);
- IMB_freeImBuf(b32buf);
}
# endif /* WITH_HEADLESS */
@@ -991,11 +1112,7 @@ ListBase *UI_iconfile_list(void)
void UI_icons_free(void)
{
#ifndef WITH_HEADLESS
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
-
+ free_icons_textures();
free_iconfile_list(&iconfilelist);
BKE_icons_free();
#endif
@@ -1109,6 +1226,7 @@ void UI_icons_init()
{
#ifndef WITH_HEADLESS
init_iconfile_list(&iconfilelist);
+ UI_icons_reload_internal_textures();
init_internal_icons();
init_brush_icons();
init_event_icons();
@@ -1440,12 +1558,17 @@ typedef struct IconDrawCall {
float color[4];
} IconDrawCall;
-static struct {
+typedef struct IconTextureDrawCall {
IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
int calls; /* Number of calls batched together */
+} IconTextureDrawCall;
+
+static struct {
+ IconTextureDrawCall normal;
+ IconTextureDrawCall border;
bool enabled;
float mat[4][4];
-} g_icon_draw_cache = {{{{0}}}};
+} g_icon_draw_cache = {{{{{0}}}}};
void UI_icon_draw_cache_begin(void)
{
@@ -1453,19 +1576,15 @@ void UI_icon_draw_cache_begin(void)
g_icon_draw_cache.enabled = true;
}
-static void icon_draw_cache_flush_ex(void)
+static void icon_draw_cache_texture_flush_ex(GLuint texture,
+ IconTextureDrawCall *texture_draw_calls)
{
- if (g_icon_draw_cache.calls == 0) {
+ if (texture_draw_calls->calls == 0) {
return;
}
- /* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
-
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glBindTexture(GL_TEXTURE_2D, texture);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1474,16 +1593,43 @@ static void icon_draw_cache_flush_ex(void)
int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
glUniform1i(img_loc, 0);
- glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
+ glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
- GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+ GPU_draw_primitive(GPU_PRIM_TRIS, 6 * texture_draw_calls->calls);
glBindTexture(GL_TEXTURE_2D, 0);
- g_icon_draw_cache.calls = 0;
+ texture_draw_calls->calls = 0;
+}
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+static void icon_draw_cache_flush_ex(bool only_full_caches)
+{
+ bool should_draw = false;
+ if (only_full_caches) {
+ should_draw = g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE ||
+ g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE;
+ }
+ else {
+ should_draw = g_icon_draw_cache.normal.calls || g_icon_draw_cache.border.calls;
+ }
+
+ if (should_draw) {
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (!only_full_caches || g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_texture_flush_ex(icongltex.id[0], &g_icon_draw_cache.normal);
+ }
+
+ if (!only_full_caches || g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_texture_flush_ex(icongltex.id[1], &g_icon_draw_cache.border);
+ }
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
}
void UI_icon_draw_cache_end(void)
@@ -1492,12 +1638,12 @@ void UI_icon_draw_cache_end(void)
g_icon_draw_cache.enabled = false;
/* Don't change blend state if it's not needed. */
- if (g_icon_draw_cache.calls == 0) {
+ if (g_icon_draw_cache.border.calls == 0 && g_icon_draw_cache.normal.calls == 0) {
return;
}
GPU_blend(true);
- icon_draw_cache_flush_ex();
+ icon_draw_cache_flush_ex(false);
GPU_blend(false);
}
@@ -1510,14 +1656,18 @@ static void icon_draw_texture_cached(float x,
int UNUSED(iw),
int ih,
float alpha,
- const float rgb[3])
+ const float rgb[3],
+ bool with_border)
{
float mvp[4][4];
GPU_matrix_model_view_projection_get(mvp);
- IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
- g_icon_draw_cache.calls++;
+ IconTextureDrawCall *texture_call = with_border ? &g_icon_draw_cache.border :
+ &g_icon_draw_cache.normal;
+
+ IconDrawCall *call = &texture_call->drawcall_cache[texture_call->calls];
+ texture_call->calls++;
/* Manual mat4*vec2 */
call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
@@ -1537,8 +1687,8 @@ static void icon_draw_texture_cached(float x,
copy_v4_fl(call->color, alpha);
}
- if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
- icon_draw_cache_flush_ex();
+ if (texture_call->calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_flush_ex(true);
}
}
@@ -1551,10 +1701,11 @@ static void icon_draw_texture(float x,
int iw,
int ih,
float alpha,
- const float rgb[3])
+ const float rgb[3],
+ bool with_border)
{
if (g_icon_draw_cache.enabled) {
- icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
+ icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1571,7 +1722,7 @@ static void icon_draw_texture(float x,
y2 = (iy + ih) * icongltex.invh;
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glBindTexture(GL_TEXTURE_2D, with_border ? icongltex.id[1] : icongltex.id[0]);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1696,10 +1847,12 @@ static void icon_draw_size(float x,
di->data.texture.w,
di->data.texture.h,
alpha,
- rgb);
+ rgb,
+ false);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
/* icon that matches text color, assumed to be white */
+ bool with_border = false;
float color[4];
if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) {
if (mono_rgba) {
@@ -1709,6 +1862,9 @@ static void icon_draw_size(float x,
UI_GetThemeColor4fv(TH_TEXT, color);
}
}
+ else {
+ with_border = (btheme->tui.icon_border_intensity > 0.0f);
+ }
if (rgb) {
mul_v3_v3(color, rgb);
@@ -1716,16 +1872,24 @@ static void icon_draw_size(float x,
mul_v4_fl(color, alpha);
- icon_draw_texture(x,
- y,
- (float)w,
- (float)h,
- di->data.texture.x,
- di->data.texture.y,
- di->data.texture.w,
- di->data.texture.h,
+ float border_outset = 0.0;
+ unsigned int border_texel = 0;
+ if (with_border) {
+ const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH;
+ border_texel = ICON_MONO_BORDER_OUTSET;
+ border_outset = ICON_MONO_BORDER_OUTSET / (scale * aspect);
+ }
+ icon_draw_texture(x - border_outset,
+ y - border_outset,
+ (float)w + 2 * border_outset,
+ (float)h + 2 * border_outset,
+ di->data.texture.x - border_texel,
+ di->data.texture.y - border_texel,
+ di->data.texture.w + 2 * border_texel,
+ di->data.texture.h + 2 * border_texel,
color[3],
- color);
+ color,
+ with_border);
}
else if (di->type == ICON_TYPE_BUFFER) {