UI: Color Icon Theme Internal Parts #125146

Merged
Harley Acheson merged 15 commits from Harley/blender:IconThemeColor into main 2024-08-11 20:10:52 +02:00
7 changed files with 207 additions and 24 deletions

View File

@ -1 +1 @@
<svg id="svg2" height="1200" viewBox="0 0 1200 1200" width="1200" xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"><sodipodi:namedview pagecolor="#303030" showgrid="true"><inkscape:grid id="grid5" units="px" spacingx="100" spacingy="100" color="#4772b3" opacity="0.2" visible="true" /></sodipodi:namedview><path id="path1" d="m286 622c-2.7555 0-5 2.2445-5 5s2.2445 5 5 5 5-2.2445 5-5-2.2445-5-5-5z" fill="#fff" transform="matrix(100 0 0 100 -27999.994 -62100)"/></svg> <svg id="svg2" height="1200" viewBox="0 0 1200 1200" width="1200" xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"><sodipodi:namedview pagecolor="#303030" showgrid="true"><inkscape:grid id="grid5" units="px" spacingx="100" spacingy="100" color="#4772b3" opacity="0.2" visible="true" /></sodipodi:namedview><g><g id="blender.red_alert" fill="#ffffff" transform="matrix(1 0 0 .99407813 0 5.93843)"><path id="path1" d="m599.97471 191.39126c-220.28631 0-403.19327 185.73026-403.19327 406.16752 0 229.42349 172.48512 404.04942 403.19327 404.04942 230.70813 0 401.14369-178.37144 401.89049-404.04942.7445-224.93037-181.60419-406.16752-401.89049-406.16752z" stroke-width="79.9717"/></g><g id="blender.text" fill="#ffffff" opacity=".8"><path id="path1-1" d="m599.88703 100.19229c-275.55 0-499.81389 224.2639-499.81389 499.8139s224.26389 499.81391 499.81389 499.81391 499.81387-224.45002 499.81387-500.00002-224.26387-499.62779-499.81387-499.62779zm0 99.62779c221.506 0 400.18607 178.68011 400.18607 400.18611s-178.68007 400.18611-400.18607 400.18611-400.55831-175.88855-400.55831-397.39455 179.05231-402.97767 400.55831-402.97767z" stroke-width="100"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 583 B

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -11,6 +11,7 @@
#include "BLI_array.hh" #include "BLI_array.hh"
#include "BLI_bounds_types.hh" #include "BLI_bounds_types.hh"
#include "BLI_compiler_attrs.h" #include "BLI_compiler_attrs.h"
#include "BLI_function_ref.hh"
#include "BLI_string_ref.hh" #include "BLI_string_ref.hh"
#include "BLI_sys_types.h" #include "BLI_sys_types.h"
#include "BLI_vector.hh" #include "BLI_vector.hh"
@ -152,7 +153,8 @@ void BLF_draw_svg_icon(uint icon_id,
float size, float size,
float color[4] = nullptr, float color[4] = nullptr,
float outline_alpha = 1.0f, float outline_alpha = 1.0f,
bool multicolor = false); bool multicolor = false,
blender::FunctionRef<void(std::string &)> edit_source_cb = nullptr);
blender::Array<uchar> BLF_svg_icon_bitmap( blender::Array<uchar> BLF_svg_icon_bitmap(
uint icon_id, float size, int *r_width, int *r_height, bool multicolor = false); uint icon_id, float size, int *r_width, int *r_height, bool multicolor = false);

View File

@ -615,7 +615,8 @@ void BLF_draw_svg_icon(uint icon_id,
float size, float size,
float color[4], float color[4],
float outline_alpha, float outline_alpha,
bool multicolor) bool multicolor,
blender::FunctionRef<void(std::string &)> edit_source_cb)
{ {
#ifndef WITH_HEADLESS #ifndef WITH_HEADLESS
FontBLF *font = global_font[0]; FontBLF *font = global_font[0];
@ -623,11 +624,11 @@ void BLF_draw_svg_icon(uint icon_id,
/* Avoid bgl usage to corrupt BLF drawing. */ /* Avoid bgl usage to corrupt BLF drawing. */
GPU_bgl_end(); GPU_bgl_end();
blf_draw_gpu__start(font); blf_draw_gpu__start(font);
blf_draw_svg_icon(font, icon_id, x, y, size, color, outline_alpha, multicolor); blf_draw_svg_icon(font, icon_id, x, y, size, color, outline_alpha, multicolor, edit_source_cb);
blf_draw_gpu__end(font); blf_draw_gpu__end(font);
} }
#else #else
UNUSED_VARS(icon_id, x, y, size, color, outline_alpha, multicolor); UNUSED_VARS(icon_id, x, y, size, color, outline_alpha, multicolor, edit_source_cb);
#endif /* WITH_HEADLESS */ #endif /* WITH_HEADLESS */
} }

View File

@ -532,7 +532,8 @@ void blf_draw_svg_icon(FontBLF *font,
float size, float size,
float color[4], float color[4],
float outline_alpha, float outline_alpha,
bool multicolor) bool multicolor,
blender::FunctionRef<void(std::string &)> edit_source_cb)
{ {
blf_font_size(font, size); blf_font_size(font, size);
font->pos[0] = int(x); font->pos[0] = int(x);
@ -557,7 +558,7 @@ void blf_draw_svg_icon(FontBLF *font,
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_batch_draw_begin(font); blf_batch_draw_begin(font);
GlyphBLF *g = blf_glyph_ensure_icon(gc, icon_id, multicolor); GlyphBLF *g = blf_glyph_ensure_icon(gc, icon_id, multicolor, edit_source_cb);
if (g) { if (g) {
blf_glyph_draw(font, gc, g, 0, 0); blf_glyph_draw(font, gc, g, 0, 0);
} }

View File

@ -352,13 +352,18 @@ static GlyphBLF *blf_glyph_cache_add_blank(GlyphCacheBLF *gc, uint charcode)
return result; return result;
} }
static GlyphBLF *blf_glyph_cache_add_svg(GlyphCacheBLF *gc, uint charcode, bool color) static GlyphBLF *blf_glyph_cache_add_svg(
GlyphCacheBLF *gc,
uint charcode,
bool color,
blender::FunctionRef<void(std::string &)> edit_source_cb = nullptr)
{ {
const char *svg_source = blf_get_icon_svg(int(charcode) - BLF_ICON_OFFSET); std::string svg_source = blf_get_icon_svg(int(charcode) - BLF_ICON_OFFSET);
/* NanoSVG alters the source file while parsing. */ if (edit_source_cb) {
char *writeable = BLI_strdup(svg_source); edit_source_cb(svg_source);
NSVGimage *image = nsvgParse(writeable, "px", 96.0f); }
MEM_freeN(writeable);
NSVGimage *image = nsvgParse(svg_source.data(), "px", 96.0f);
if (image == nullptr) { if (image == nullptr) {
return blf_glyph_cache_add_blank(gc, charcode); return blf_glyph_cache_add_blank(gc, charcode);
@ -1393,13 +1398,16 @@ GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, const uint charcode
} }
#ifndef WITH_HEADLESS #ifndef WITH_HEADLESS
GlyphBLF *blf_glyph_ensure_icon(GlyphCacheBLF *gc, const uint icon_id, bool color) GlyphBLF *blf_glyph_ensure_icon(GlyphCacheBLF *gc,
const uint icon_id,
bool color,
blender::FunctionRef<void(std::string &)> edit_source_cb)
{ {
GlyphBLF *g = blf_glyph_cache_find_glyph(gc, icon_id + BLF_ICON_OFFSET, 0); GlyphBLF *g = blf_glyph_cache_find_glyph(gc, icon_id + BLF_ICON_OFFSET, 0);
if (g) { if (g) {
return g; return g;
} }
return blf_glyph_cache_add_svg(gc, icon_id + BLF_ICON_OFFSET, color); return blf_glyph_cache_add_svg(gc, icon_id + BLF_ICON_OFFSET, color, edit_source_cb);
} }
#endif /* WITH_HEADLESS */ #endif /* WITH_HEADLESS */

View File

@ -10,6 +10,7 @@
#include "BLI_array.hh" #include "BLI_array.hh"
#include "BLI_bounds_types.hh" #include "BLI_bounds_types.hh"
#include "BLI_function_ref.hh"
#include "BLI_string_ref.hh" #include "BLI_string_ref.hh"
#include "BLI_vector.hh" #include "BLI_vector.hh"
@ -107,7 +108,8 @@ void blf_draw_svg_icon(FontBLF *font,
float size, float size,
float color[4] = nullptr, float color[4] = nullptr,
float outline_alpha = 1.0f, float outline_alpha = 1.0f,
bool multicolor = false); bool multicolor = false,
blender::FunctionRef<void(std::string &)> edit_source_cb = nullptr);
blender::Array<uchar> blf_svg_icon_bitmap( blender::Array<uchar> blf_svg_icon_bitmap(
FontBLF *font, uint icon_id, float size, int *r_width, int *r_height, bool multicolor = false); FontBLF *font, uint icon_id, float size, int *r_width, int *r_height, bool multicolor = false);
@ -185,7 +187,11 @@ GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode, uint
GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x); GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x);
#endif #endif
GlyphBLF *blf_glyph_ensure_icon(GlyphCacheBLF *gc, uint icon_id, bool color = false); GlyphBLF *blf_glyph_ensure_icon(
GlyphCacheBLF *gc,
uint icon_id,
bool color = false,
blender::FunctionRef<void(std::string &)> edit_source_cb = nullptr);
/** /**
* Convert a character's outlines into curves. * Convert a character's outlines into curves.

View File

@ -49,6 +49,8 @@
#include "interface_intern.hh" #include "interface_intern.hh"
#include "fmt/format.h"
struct IconImage { struct IconImage {
int w; int w;
int h; int h;
@ -1295,6 +1297,155 @@ static int get_draw_size(enum eIconSizes size)
} }
} }
static void svg_replace_color_attributes(std::string &svg,
const std::string &name,
const size_t start,
const size_t end)
{
bTheme *btheme = UI_GetTheme();
uchar white[] = {255, 255, 255, 255};
uchar black[] = {0, 0, 0, 255};
uchar logo_orange[] = {232, 125, 13, 255};
uchar logo_blue[] = {38, 87, 135, 255};
/* Tool colors hardcoded for now. */
uchar tool_add[] = {117, 255, 175, 255};
uchar tool_remove[] = {245, 107, 91, 255};
uchar tool_select[] = {255, 176, 43, 255};
uchar tool_transform[] = {217, 175, 245, 255};
uchar tool_white[] = {255, 255, 255, 255};
uchar tool_red[] = {214, 45, 48, 255};
struct ColorItem {
const char *name;
uchar *col = nullptr;
int colorid = TH_UNDEFINED;
int spacetype = SPACE_TYPE_ANY;
} items[] = {
{"blender.white", white},
{"blender.black", black},
{"blender.logo_orange", logo_orange},
{"blender.logo_blue", logo_blue},
{"blender.selected", btheme->tui.wcol_regular.inner},
{"blender.mesh_selected", btheme->space_view3d.vertex_select},
{"blender.back", nullptr, TH_BACK},
{"blender.text", nullptr, TH_TEXT},
{"blender.text_hi", nullptr, TH_TEXT_HI},
{"blender.red_alert", nullptr, TH_REDALERT},
{"blender.error", nullptr, TH_INFO_ERROR, SPACE_INFO},
{"blender.warning", nullptr, TH_INFO_WARNING, SPACE_INFO},
{"blender.info", nullptr, TH_INFO_INFO, SPACE_INFO},
{"blender.scene", nullptr, TH_ICON_SCENE},
{"blender.collection", nullptr, TH_ICON_COLLECTION},
{"blender.object", nullptr, TH_ICON_OBJECT},
{"blender.object_data", nullptr, TH_ICON_OBJECT_DATA},
{"blender.modifier", nullptr, TH_ICON_MODIFIER},
{"blender.shading", nullptr, TH_ICON_SHADING},
{"blender.folder", nullptr, TH_ICON_FOLDER},
{"blender.fund", nullptr, TH_ICON_FUND},
{"blender.tool_add", tool_add},
{"blender.tool_remove", tool_remove},
{"blender.tool_select", tool_select},
{"blender.tool_transform", tool_transform},
{"blender.tool_white", tool_white},
{"blender.tool_red", tool_red},
};
for (const ColorItem &item : items) {
if (name != item.name) {
continue;
}
uchar color[4];
if (item.col) {
memcpy(color, item.col, sizeof(color));
}
else if (item.colorid != TH_UNDEFINED) {
if (item.spacetype != SPACE_TYPE_ANY) {
UI_GetThemeColorType4ubv(item.colorid, item.spacetype, color);
}
else {
UI_GetThemeColor4ubv(item.colorid, color);
}
}
else {
continue;
}
std::string hexcolor = fmt::format(
"{:02x}{:02x}{:02x}{:02x}", color[0], color[1], color[2], color[3]);
size_t att_start = start;
while (1) {
constexpr static blender::StringRef key = "fill=\"";
att_start = svg.find(key, att_start);
if (att_start == std::string::npos || att_start > end) {
break;
}
const size_t att_end = svg.find("\"", att_start + key.size());
if (att_end != std::string::npos && att_end < end) {
svg.replace(att_start, att_end - att_start, key + "#" + hexcolor);
}
att_start += blender::StringRef(key + "#rrggbbaa\"").size();
}
att_start = start;
while (1) {
constexpr static blender::StringRef key = "fill:";
att_start = svg.find(key, att_start);
if (att_start == std::string::npos || att_start > end) {
break;
}
const size_t att_end = svg.find(";", att_start + key.size());
if (att_end != std::string::npos && att_end - att_start < end) {
svg.replace(att_start, att_end - att_start, key + "#" + hexcolor);
}
att_start += blender::StringRef(key + "#rrggbbaa").size();
}
}
}
static void icon_source_edit_cb(std::string &svg)
{
size_t g_start = 0;
/* Scan string, processing only groups with our keyword ids. */
while (1) {
/* Look for a blender id, quick exit if not found. */
constexpr static blender::StringRef key = "id=\"";
const size_t id_start = svg.find(key + "blender.", g_start);
if (id_start == std::string::npos) {
return;
}
/* Scan back to beginning of this group element. */
g_start = svg.rfind("<g", id_start);
if (g_start == std::string::npos) {
/* Malformed. */
return;
}
/* Scan forward to end of the group. */
const size_t g_end = svg.find("</g>", id_start);
if (g_end == std::string::npos) {
/* Malformed. */
return;
}
/* Get group id name. */
const size_t id_end = svg.find("\"", id_start + key.size());
if (id_end != std::string::npos) {
std::string id_name = svg.substr(id_start + key.size(), id_end - id_start - key.size());
/* Replace this group's colors. */
svg_replace_color_attributes(svg, id_name, g_start, g_end);
}
g_start = g_end;
}
}
static void icon_draw_size(float x, static void icon_draw_size(float x,
float y, float y,
int icon_id, int icon_id,
@ -1398,13 +1549,27 @@ static void icon_draw_size(float x,
} }
color[3] *= alpha; color[3] *= alpha;
BLF_draw_svg_icon(uint(icon_id),
x, if (di->type == ICON_TYPE_SVG_COLOR) {
y, BLF_draw_svg_icon(uint(icon_id),
float(draw_size) / aspect, x,
color, y,
outline_intensity, float(draw_size) / aspect,
di->type == ICON_TYPE_SVG_COLOR); color,
outline_intensity,
true,
icon_source_edit_cb);
}
else {
BLF_draw_svg_icon(uint(icon_id),
x,
y,
float(draw_size) / aspect,
color,
outline_intensity,
false,
nullptr);
}
if (text_overlay && text_overlay->text[0] != '\0') { if (text_overlay && text_overlay->text[0] != '\0') {
/* Handle the little numbers on top of the icon. */ /* Handle the little numbers on top of the icon. */