Blender V4.3
interface_style.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <climits>
10#include <cmath>
11#include <cstdio>
12#include <cstdlib>
13#include <cstring>
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_userdef_types.h"
18
19#include "BLI_listbase.h"
20#include "BLI_rect.h"
21#include "BLI_string.h"
22#include "BLI_utildefines.h"
23
24#include "BKE_global.hh"
25
26#include "BLF_api.hh"
27
28#include "UI_interface.hh"
29
30#include "interface_intern.hh"
31
32#ifdef WIN32
33# include "BLI_math_base.h" /* M_PI */
34#endif
35
36static void fontstyle_set_ex(const uiFontStyle *fs, const float dpi_fac);
37
38/* style + theme + layout-engine = UI */
39
55/* ********************************************** */
56
57static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id)
58{
59 uiStyle *style = MEM_cnew<uiStyle>(__func__);
60
61 BLI_addtail(styles, style);
62 STRNCPY(style->name, name);
63
64 style->panelzoom = 1.0; /* unused */
65
66 style->paneltitle.uifont_id = uifont_id;
68 style->paneltitle.character_weight = 400;
69 style->paneltitle.shadow = 3;
70 style->paneltitle.shadx = 0;
71 style->paneltitle.shady = -1;
72 style->paneltitle.shadowalpha = 0.5f;
73 style->paneltitle.shadowcolor = 0.0f;
74
75 style->grouplabel.uifont_id = uifont_id;
77 style->grouplabel.character_weight = 400;
78 style->grouplabel.shadow = 3;
79 style->grouplabel.shadx = 0;
80 style->grouplabel.shady = -1;
81 style->grouplabel.shadowalpha = 0.5f;
82 style->grouplabel.shadowcolor = 0.0f;
83
84 style->widget.uifont_id = uifont_id;
86 style->widget.character_weight = 400;
87 style->widget.shadow = 1;
88 style->widget.shady = -1;
89 style->widget.shadowalpha = 0.5f;
90 style->widget.shadowcolor = 0.0f;
91
92 style->tooltip.uifont_id = uifont_id;
94 style->tooltip.character_weight = 400;
95 style->tooltip.shadow = 1;
96 style->tooltip.shady = -1;
97 style->tooltip.shadowalpha = 0.5f;
98 style->tooltip.shadowcolor = 0.0f;
99
100 style->columnspace = 8;
101 style->templatespace = 5;
102 style->boxspace = 5;
103 style->buttonspacex = 8;
104 style->buttonspacey = 2;
105 style->panelspace = 8;
106 style->panelouter = 4;
107
108 return style;
109}
110
112{
113 uiFont *font = static_cast<uiFont *>(U.uifonts.first);
114
115 for (; font; font = font->next) {
116 if (font->uifont_id == id) {
117 return font;
118 }
119 }
120 return static_cast<uiFont *>(U.uifonts.first);
121}
122
123/* *************** draw ************************ */
124
126 const rcti *rect,
127 const char *str,
128 const size_t str_len,
129 const uchar col[4],
130 const uiFontStyleDraw_Params *fs_params,
131 int *r_xofs,
132 int *r_yofs,
133 ResultBLF *r_info)
134{
135 int xofs = 0, yofs;
136 int font_flag = BLF_CLIPPING;
137
139
140 /* set the flag */
141 if (fs->shadow) {
142 font_flag |= BLF_SHADOW;
143 const float shadow_color[4] = {
145 BLF_shadow(fs->uifont_id, FontShadowType(fs->shadow), shadow_color);
146 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
147 }
148 if (fs_params->word_wrap == 1) {
149 font_flag |= BLF_WORD_WRAP;
150 }
151 if (fs->bold) {
152 font_flag |= BLF_BOLD;
153 }
154 if (fs->italic) {
155 font_flag |= BLF_ITALIC;
156 }
157
158 BLF_enable(fs->uifont_id, font_flag);
159
160 if (fs_params->word_wrap == 1) {
161 /* Draw from bound-box top. */
162 yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
163 }
164 else {
165 /* Draw from bound-box center. */
166 const int height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
167 yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
168 }
169
170 if (fs_params->align == UI_STYLE_TEXT_CENTER) {
171 xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, str_len)));
172 }
173 else if (fs_params->align == UI_STYLE_TEXT_RIGHT) {
174 xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, str_len);
175 }
176
177 yofs = std::max(0, yofs);
178 xofs = std::max(0, xofs);
179
180 BLF_clipping(fs->uifont_id, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
181 BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
183
184 BLF_draw(fs->uifont_id, str, str_len, r_info);
185
186 BLF_disable(fs->uifont_id, font_flag);
187
188 if (r_xofs) {
189 *r_xofs = xofs;
190 }
191 if (r_yofs) {
192 *r_yofs = yofs;
193 }
194}
195
197 const rcti *rect,
198 const char *str,
199 const size_t str_len,
200 const uchar col[4],
201 const uiFontStyleDraw_Params *fs_params)
202{
203 UI_fontstyle_draw_ex(fs, rect, str, str_len, col, fs_params, nullptr, nullptr, nullptr);
204}
205
207 const rcti *rect,
208 const char *str,
209 const uchar col[4])
210{
211 float height;
212 int xofs, yofs;
213 float angle;
214 rcti txtrect;
215
217
218 height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
219 /* becomes x-offset when rotated */
220 xofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
221
222 /* ignore UI_STYLE, always aligned to top */
223
224 /* Rotate counter-clockwise for now (assumes left-to-right language). */
225 xofs += height;
227 angle = M_PI_2;
228
229 /* translate rect to vertical */
230 txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
231 txtrect.ymin = rect->ymin - BLI_rcti_size_x(rect);
232 txtrect.xmax = rect->xmin;
233 txtrect.ymax = rect->ymin;
234
235 /* clip is very strict, so we give it some space */
236 /* clipping is done without rotation, so make rect big enough to contain both positions */
238 txtrect.xmin - 1,
239 txtrect.ymin - yofs - xofs - 4,
240 rect->xmax + 1,
241 rect->ymax + 4);
243 BLF_position(fs->uifont_id, txtrect.xmin + xofs, txtrect.ymax - yofs, 0.0f);
244
246 BLF_rotation(fs->uifont_id, angle);
248
249 if (fs->shadow) {
251 const float shadow_color[4] = {
253 BLF_shadow(fs->uifont_id, FontShadowType(fs->shadow), shadow_color);
254 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
255 }
256
260 if (fs->shadow) {
262 }
263}
264
266 const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
267{
269 BLF_position(fs->uifont_id, x, y, 0.0f);
272}
273
275 float x,
276 float y,
278 const float col_fg[4],
279 const float col_bg[4])
280{
282
283 {
284 const int width = BLF_width(fs->uifont_id, str.data(), str.size());
285 const int height = BLF_height_max(fs->uifont_id);
286 const int decent = BLF_descender(fs->uifont_id);
287 const float margin = height / 4.0f;
288
289 rctf rect;
290 rect.xmin = x - margin;
291 rect.xmax = x + width + margin;
292 rect.ymin = (y + decent) - margin;
293 rect.ymax = (y + decent) + height + margin;
295 UI_draw_roundbox_4fv(&rect, true, margin, col_bg);
296 }
297
298 BLF_position(fs->uifont_id, x, y, 0.0f);
299 BLF_color4fv(fs->uifont_id, col_fg);
300 BLF_draw(fs->uifont_id, str.data(), str.size());
301}
302
303/* ************** helpers ************************ */
304
306{
307#if 0
308 uiStyle *style = nullptr;
309 /* offset is two struct uiStyle pointers */
310 style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
311 return (style != nullptr) ? style : U.uistyles.first;
312#else
313 return static_cast<const uiStyle *>(U.uistyles.first);
314#endif
315}
316
318{
319 const uiStyle *style = UI_style_get();
320 static uiStyle _style;
321
322 _style = *style;
323
324 _style.paneltitle.shadx = short(UI_SCALE_FAC * _style.paneltitle.shadx);
325 _style.paneltitle.shady = short(UI_SCALE_FAC * _style.paneltitle.shady);
326 _style.grouplabel.shadx = short(UI_SCALE_FAC * _style.grouplabel.shadx);
327 _style.grouplabel.shady = short(UI_SCALE_FAC * _style.grouplabel.shady);
328 _style.widget.shadx = short(UI_SCALE_FAC * _style.widget.shadx);
329 _style.widget.shady = short(UI_SCALE_FAC * _style.widget.shady);
330 _style.tooltip.shadx = short(UI_SCALE_FAC * _style.tooltip.shadx);
331 _style.tooltip.shady = short(UI_SCALE_FAC * _style.tooltip.shady);
332
333 _style.columnspace = short(UI_SCALE_FAC * _style.columnspace);
334 _style.templatespace = short(UI_SCALE_FAC * _style.templatespace);
335 _style.boxspace = short(UI_SCALE_FAC * _style.boxspace);
336 _style.buttonspacex = short(UI_SCALE_FAC * _style.buttonspacex);
337 _style.buttonspacey = short(UI_SCALE_FAC * _style.buttonspacey);
338 _style.panelspace = short(UI_SCALE_FAC * _style.panelspace);
339 _style.panelouter = short(UI_SCALE_FAC * _style.panelouter);
340
341 return &_style;
342}
343
344int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str)
345{
348}
349
351 const char *str,
352 const float aspect)
353{
354 /* FIXME(@ideasman42): the final scale of the font is rounded which should be accounted for.
355 * Failing to do so causes bad alignment when zoomed out very far in the node-editor. */
356 fontstyle_set_ex(fs, UI_SCALE_FAC / aspect);
357 return int(BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) * aspect);
358}
359
361{
363 return BLF_height_max(fs->uifont_id);
364}
365
366/* ************** init exit ************************ */
367
369{
370 const uiStyle *style = static_cast<uiStyle *>(U.uistyles.first);
371
372 /* Recover from uninitialized DPI. */
373 if (U.dpi == 0) {
374 U.dpi = 72;
375 }
376 CLAMP(U.dpi, 48, 144);
377
378 /* Needed so that custom fonts are always first. */
380
381 uiFont *font_first = static_cast<uiFont *>(U.uifonts.first);
382
383 /* default builtin */
384 if (font_first == nullptr) {
385 font_first = MEM_cnew<uiFont>(__func__);
386 BLI_addtail(&U.uifonts, font_first);
387 }
388
389 if (U.font_path_ui[0]) {
390 STRNCPY(font_first->filepath, U.font_path_ui);
391 font_first->uifont_id = UIFONT_CUSTOM1;
392 }
393 else {
394 STRNCPY(font_first->filepath, "default");
395 font_first->uifont_id = UIFONT_DEFAULT;
396 }
397
398 LISTBASE_FOREACH (uiFont *, font, &U.uifonts) {
399 const bool unique = false;
400
401 if (font->uifont_id == UIFONT_DEFAULT) {
402 font->blf_id = BLF_load_default(unique);
403 }
404 else {
405 font->blf_id = BLF_load(font->filepath);
406 if (font->blf_id == -1) {
407 font->blf_id = BLF_load_default(unique);
408 }
409 }
410
411 BLF_default_set(font->blf_id);
412
413 if (font->blf_id == -1) {
414 if (G.debug & G_DEBUG) {
415 printf("%s: error, no fonts available\n", __func__);
416 }
417 }
418 }
419
420 if (style == nullptr) {
421 style = ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
422 }
423
425
427
428 /* XXX, this should be moved into a style,
429 * but for now best only load the monospaced font once. */
431 /* Use unique font loading to avoid thread safety issues with mono font
432 * used for render metadata stamp in threads. */
433 if (U.font_path_ui_mono[0]) {
434 blf_mono_font = BLF_load_unique(U.font_path_ui_mono);
435 }
436 if (blf_mono_font == -1) {
437 const bool unique = true;
439 }
440
441 /* Set default flags based on UI preferences (not render fonts) */
442 {
443 const int flag_disable = (BLF_MONOCHROME | BLF_HINTING_NONE | BLF_HINTING_SLIGHT |
445 int flag_enable = 0;
446
447 if (U.text_render & USER_TEXT_HINTING_NONE) {
448 flag_enable |= BLF_HINTING_NONE;
449 }
450 else if (U.text_render & USER_TEXT_HINTING_SLIGHT) {
451 flag_enable |= BLF_HINTING_SLIGHT;
452 }
453 else if (U.text_render & USER_TEXT_HINTING_FULL) {
454 flag_enable |= BLF_HINTING_FULL;
455 }
456
457 if (U.text_render & USER_TEXT_DISABLE_AA) {
458 flag_enable |= BLF_MONOCHROME;
459 }
460 else {
461 if (U.text_render & USER_TEXT_RENDER_SUBPIXELAA) {
462 flag_enable |= BLF_RENDER_SUBPIXELAA;
463 }
464 }
465
466 LISTBASE_FOREACH (uiFont *, font, &U.uifonts) {
467 if (font->blf_id != -1) {
468 BLF_disable(font->blf_id, flag_disable);
469 BLF_enable(font->blf_id, flag_enable);
470 }
471 }
472 if (blf_mono_font != -1) {
473 BLF_disable(blf_mono_font, flag_disable);
474 BLF_enable(blf_mono_font, flag_enable);
475 }
476 }
477
484 if (blf_mono_font_render == -1) {
485 const bool unique = true;
487 }
488
489 /* Load the fallback fonts last. */
491}
492
493static void fontstyle_set_ex(const uiFontStyle *fs, const float dpi_fac)
494{
495 const uiFont *font = uifont_to_blfont(fs->uifont_id);
496
497 BLF_size(font->blf_id, fs->points * dpi_fac);
498 BLF_character_weight(font->blf_id, fs->character_weight);
499}
500
502{
504}
@ G_DEBUG
void BLF_size(int fontid, float size)
Definition blf.cc:426
void BLF_default_set(int fontid)
int BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:850
void BLF_shadow(int fontid, FontShadowType type, const float rgba[4]=nullptr)
Definition blf.cc:902
void BLF_unload_all()
Definition blf.cc:298
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax)
Definition blf.cc:881
int BLF_load_default(bool unique)
void BLF_cache_flush_set_fn(void(*cache_flush_fn)())
Definition blf_font.cc:1523
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:488
void BLF_shadow_offset(int fontid, int x, int y)
Definition blf.cc:914
int blf_mono_font_render
Definition blf.cc:52
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:393
void BLF_disable(int fontid, int option)
Definition blf.cc:321
void BLF_rotation(int fontid, float angle)
Definition blf.cc:872
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:568
void BLF_default_size(float size)
int BLF_load_mono_default(bool unique)
int BLF_load(const char *filepath) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition blf.cc:174
int blf_mono_font
Definition blf.cc:51
int BLF_load_unique(const char *filepath) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition blf.cc:187
void BLF_load_font_stack()
void BLF_enable(int fontid, int option)
Definition blf.cc:312
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:791
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:828
FontShadowType
Definition BLF_api.hh:33
@ BLF_RENDER_SUBPIXELAA
Definition BLF_api.hh:390
@ BLF_ITALIC
Definition BLF_api.hh:374
@ BLF_ROTATION
Definition BLF_api.hh:361
@ BLF_HINTING_NONE
Definition BLF_api.hh:370
@ BLF_WORD_WRAP
Definition BLF_api.hh:367
@ BLF_MONOCHROME
Definition BLF_api.hh:369
@ BLF_BOLD
Definition BLF_api.hh:373
@ BLF_HINTING_FULL
Definition BLF_api.hh:372
@ BLF_HINTING_SLIGHT
Definition BLF_api.hh:371
@ BLF_SHADOW
Definition BLF_api.hh:363
@ BLF_CLIPPING
Definition BLF_api.hh:362
void BLF_color4ubv(int fontid, const unsigned char rgba[4])
Definition blf.cc:435
int BLF_ascender(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:861
void BLF_character_weight(int fontid, int weight)
Definition blf.cc:330
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:371
#define BLI_assert(a)
Definition BLI_assert.h:50
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
#define M_PI_2
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned char uchar
#define CLAMP(a, b, c)
@ UIFONT_DEFAULT
@ UIFONT_CUSTOM1
@ USER_TEXT_HINTING_SLIGHT
@ USER_TEXT_HINTING_FULL
@ USER_TEXT_DISABLE_AA
@ USER_TEXT_HINTING_NONE
@ USER_TEXT_RENDER_SUBPIXELAA
#define UI_SCALE_FAC
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4])
#define UI_DEFAULT_TOOLTIP_POINTS
void UI_draw_roundbox_corner_set(int type)
@ UI_STYLE_TEXT_CENTER
@ UI_STYLE_TEXT_RIGHT
#define UI_DEFAULT_TITLE_POINTS
@ UI_CNR_ALL
#define UI_DEFAULT_TEXT_POINTS
void UI_widgetbase_draw_cache_flush()
unsigned int U
Definition btGjkEpa3.h:78
#define printf
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define str(s)
uint col
int UI_fontstyle_string_width_with_block_aspect(const uiFontStyle *fs, const char *str, const float aspect)
static uiStyle * ui_style_new(ListBase *styles, const char *name, short uifont_id)
void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str)
void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs, float x, float y, const blender::StringRef str, const float col_fg[4], const float col_bg[4])
void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, const size_t str_len, const uchar col[4], const uiFontStyleDraw_Params *fs_params)
const uiStyle * UI_style_get_dpi()
void uiStyleInit()
int UI_fontstyle_height_max(const uiFontStyle *fs)
void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const uchar col[4])
const uiStyle * UI_style_get()
void UI_fontstyle_set(const uiFontStyle *fs)
void UI_fontstyle_draw_ex(const uiFontStyle *fs, const rcti *rect, const char *str, const size_t str_len, const uchar col[4], const uiFontStyleDraw_Params *fs_params, int *r_xofs, int *r_yofs, ResultBLF *r_info)
static void fontstyle_set_ex(const uiFontStyle *fs, const float dpi_fac)
static uiFont * uifont_to_blfont(int id)
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
#define G(x, y, z)
float xmax
float xmin
float ymax
float ymin
int ymin
int ymax
int xmin
int xmax
char filepath[1024]
short uifont_id
uiFontStyle tooltip
uiFontStyle paneltitle
uiFontStyle grouplabel
short templatespace
uiFontStyle widget
char name[64]