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:
authorHans Goudey <h.goudey@me.com>2021-04-29 07:32:55 +0300
committerHans Goudey <h.goudey@me.com>2021-04-29 07:32:55 +0300
commit2038250c62fa3753fcc31129f8dd5f4fdf08e2e7 (patch)
tree013d5ca0f535ebae01f3b03731cc507520a414c7 /source/blender/editors/interface/interface_style.cc
parent38ebac86cc28e53d7640dcc8ce3bc4edbb8f2a1b (diff)
WIP changes to compiling interface directory as C++ codetemp-interface-cpp
Diffstat (limited to 'source/blender/editors/interface/interface_style.cc')
-rw-r--r--source/blender/editors/interface/interface_style.cc577
1 files changed, 577 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_style.cc b/source/blender/editors/interface/interface_style.cc
new file mode 100644
index 00000000000..b3aca8f9ea2
--- /dev/null
+++ b/source/blender/editors/interface/interface_style.cc
@@ -0,0 +1,577 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edinterface
+ */
+
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_global.h"
+
+#include "BLF_api.h"
+#ifdef WITH_INTERNATIONAL
+# include "BLT_translation.h"
+#endif
+
+#include "UI_interface.h"
+
+#include "ED_datafiles.h"
+
+#include "interface_intern.h"
+
+#ifdef WIN32
+# include "BLI_math_base.h" /* M_PI */
+#endif
+
+/* style + theme + layout-engine = UI */
+
+/**
+ * This is a complete set of layout rules, the 'state' of the Layout
+ * Engine. Multiple styles are possible, defined via C or Python. Styles
+ * get a name, and will typically get activated per region type, like
+ * "Header", or "Listview" or "Toolbar". Properties of Style definitions
+ * are:
+ *
+ * - default column properties, internal spacing, aligning, min/max width
+ * - button alignment rules (for groups)
+ * - label placement rules
+ * - internal labeling or external labeling default
+ * - default minimum widths for buttons/labels (in amount of characters)
+ * - font types, styles and relative sizes for Panel titles, labels, etc.
+ */
+
+/* ********************************************** */
+
+static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id)
+{
+ uiStyle *style = (uiStyle *)MEM_callocN(sizeof(uiStyle), "new style");
+
+ BLI_addtail(styles, style);
+ BLI_strncpy(style->name, name, MAX_STYLE_NAME);
+
+ style->panelzoom = 1.0; /* unused */
+
+ style->paneltitle.uifont_id = uifont_id;
+ style->paneltitle.points = UI_DEFAULT_TITLE_POINTS;
+ style->paneltitle.kerning = 1;
+ style->paneltitle.shadow = 3;
+ style->paneltitle.shadx = 0;
+ style->paneltitle.shady = -1;
+ style->paneltitle.shadowalpha = 0.5f;
+ style->paneltitle.shadowcolor = 0.0f;
+
+ style->grouplabel.uifont_id = uifont_id;
+ style->grouplabel.points = UI_DEFAULT_TITLE_POINTS;
+ style->grouplabel.kerning = 1;
+ style->grouplabel.shadow = 3;
+ style->grouplabel.shadx = 0;
+ style->grouplabel.shady = -1;
+ style->grouplabel.shadowalpha = 0.5f;
+ style->grouplabel.shadowcolor = 0.0f;
+
+ style->widgetlabel.uifont_id = uifont_id;
+ style->widgetlabel.points = UI_DEFAULT_TEXT_POINTS;
+ style->widgetlabel.kerning = 1;
+ style->widgetlabel.shadow = 3;
+ style->widgetlabel.shadx = 0;
+ style->widgetlabel.shady = -1;
+ style->widgetlabel.shadowalpha = 0.5f;
+ style->widgetlabel.shadowcolor = 0.0f;
+
+ style->widget.uifont_id = uifont_id;
+ style->widget.points = UI_DEFAULT_TEXT_POINTS;
+ style->widget.kerning = 1;
+ style->widget.shadow = 1;
+ style->widget.shady = -1;
+ style->widget.shadowalpha = 0.5f;
+ style->widget.shadowcolor = 0.0f;
+
+ style->columnspace = 8;
+ style->templatespace = 5;
+ style->boxspace = 5;
+ style->buttonspacex = 8;
+ style->buttonspacey = 2;
+ style->panelspace = 8;
+ style->panelouter = 4;
+
+ return style;
+}
+
+static uiFont *uifont_to_blfont(int id)
+{
+ uiFont *font = (uiFont *)U.uifonts.first;
+
+ for (; font; font = font->next) {
+ if (font->uifont_id == id) {
+ return font;
+ }
+ }
+ return (uiFont *)U.uifonts.first;
+}
+
+/* *************** draw ************************ */
+
+void UI_fontstyle_draw_ex(const uiFontStyle *fs,
+ const rcti *rect,
+ const char *str,
+ const uchar col[4],
+ const struct uiFontStyleDraw_Params *fs_params,
+ size_t len,
+ int *r_xofs,
+ int *r_yofs,
+ struct ResultBLF *r_info)
+{
+ int xofs = 0, yofs;
+ int font_flag = BLF_CLIPPING;
+
+ UI_fontstyle_set(fs);
+
+ /* set the flag */
+ if (fs->shadow) {
+ font_flag |= BLF_SHADOW;
+ const float shadow_color[4] = {
+ fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha};
+ BLF_shadow(fs->uifont_id, fs->shadow, shadow_color);
+ BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
+ }
+ if (fs->kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ if (fs_params->word_wrap == 1) {
+ font_flag |= BLF_WORD_WRAP;
+ }
+ if (fs->bold) {
+ font_flag |= BLF_BOLD;
+ }
+ if (fs->italic) {
+ font_flag |= BLF_ITALIC;
+ }
+
+ BLF_enable(fs->uifont_id, font_flag);
+
+ if (fs_params->word_wrap == 1) {
+ /* draw from boundbox top */
+ yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
+ }
+ else {
+ /* draw from boundbox center */
+ const float height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
+ yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+ }
+
+ if (fs_params->align == UI_STYLE_TEXT_CENTER) {
+ xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
+ }
+ else if (fs_params->align == UI_STYLE_TEXT_RIGHT) {
+ xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len);
+ }
+
+ yofs = MAX2(0, yofs);
+ xofs = MAX2(0, xofs);
+
+ BLF_clipping(fs->uifont_id, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
+
+ BLF_draw_ex(fs->uifont_id, str, len, r_info);
+
+ BLF_disable(fs->uifont_id, font_flag);
+
+ if (r_xofs) {
+ *r_xofs = xofs;
+ }
+ if (r_yofs) {
+ *r_yofs = yofs;
+ }
+}
+
+void UI_fontstyle_draw(const uiFontStyle *fs,
+ const rcti *rect,
+ const char *str,
+ const uchar col[4],
+ const struct uiFontStyleDraw_Params *fs_params)
+{
+ int xofs, yofs;
+
+ UI_fontstyle_draw_ex(fs, rect, str, col, fs_params, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs, NULL);
+}
+
+/* drawn same as above, but at 90 degree angle */
+void UI_fontstyle_draw_rotated(const uiFontStyle *fs,
+ const rcti *rect,
+ const char *str,
+ const uchar col[4])
+{
+ float height;
+ int xofs, yofs;
+ float angle;
+ rcti txtrect;
+
+ UI_fontstyle_set(fs);
+
+ height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
+ /* becomes x-offset when rotated */
+ xofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+
+ /* ignore UI_STYLE, always aligned to top */
+
+ /* rotate counter-clockwise for now (assumes left-to-right language)*/
+ xofs += height;
+ yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5;
+ angle = M_PI_2;
+
+ /* translate rect to vertical */
+ txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
+ txtrect.ymin = rect->ymin - BLI_rcti_size_x(rect);
+ txtrect.xmax = rect->xmin;
+ txtrect.ymax = rect->ymin;
+
+ /* clip is very strict, so we give it some space */
+ /* clipping is done without rotation, so make rect big enough to contain both positions */
+ BLF_clipping(fs->uifont_id,
+ txtrect.xmin - 1,
+ txtrect.ymin - yofs - xofs - 4,
+ rect->xmax + 1,
+ rect->ymax + 4);
+ BLF_enable(fs->uifont_id, BLF_CLIPPING);
+ BLF_position(fs->uifont_id, txtrect.xmin + xofs, txtrect.ymax - yofs, 0.0f);
+
+ BLF_enable(fs->uifont_id, BLF_ROTATION);
+ BLF_rotation(fs->uifont_id, angle);
+ BLF_color4ubv(fs->uifont_id, col);
+
+ if (fs->shadow) {
+ BLF_enable(fs->uifont_id, BLF_SHADOW);
+ const float shadow_color[4] = {
+ fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha};
+ BLF_shadow(fs->uifont_id, fs->shadow, shadow_color);
+ BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
+ }
+
+ if (fs->kerning == 1) {
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_disable(fs->uifont_id, BLF_ROTATION);
+ BLF_disable(fs->uifont_id, BLF_CLIPPING);
+ if (fs->shadow) {
+ BLF_disable(fs->uifont_id, BLF_SHADOW);
+ }
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+}
+
+/**
+ * Similar to #UI_fontstyle_draw
+ * but ignore alignment, shadow & no clipping rect.
+ *
+ * For drawing on-screen labels.
+ */
+void UI_fontstyle_draw_simple(
+ const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
+{
+ if (fs->kerning == 1) {
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ UI_fontstyle_set(fs);
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+}
+
+/**
+ * Same as #UI_fontstyle_draw but draw a colored backdrop.
+ */
+void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs,
+ float x,
+ float y,
+ const char *str,
+ const float col_fg[4],
+ const float col_bg[4])
+{
+ if (fs->kerning == 1) {
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ UI_fontstyle_set(fs);
+
+ {
+ const float width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ const float height = BLF_height_max(fs->uifont_id);
+ const float decent = BLF_descender(fs->uifont_id);
+ const float margin = height / 4.0f;
+
+ /* backdrop */
+ const float color[4] = {col_bg[0], col_bg[1], col_bg[2], 0.5f};
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(
+ &(const rctf){
+ .xmin = x - margin,
+ .xmax = x + width + margin,
+ .ymin = (y + decent) - margin,
+ .ymax = (y + decent) + height + margin,
+ },
+ true,
+ margin,
+ color);
+ }
+
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4fv(fs->uifont_id, col_fg);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+}
+
+/* ************** helpers ************************ */
+/* XXX: read a style configure */
+const uiStyle *UI_style_get(void)
+{
+#if 0
+ uiStyle *style = NULL;
+ /* offset is two struct uiStyle pointers */
+ style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
+ return (style != NULL) ? style : U.uistyles.first;
+#else
+ return (uiStyle *)U.uistyles.first;
+#endif
+}
+
+/* for drawing, scaled with DPI setting */
+const uiStyle *UI_style_get_dpi(void)
+{
+ const uiStyle *style = UI_style_get();
+ static uiStyle _style;
+
+ _style = *style;
+
+ _style.paneltitle.shadx = (short)(UI_DPI_FAC * _style.paneltitle.shadx);
+ _style.paneltitle.shady = (short)(UI_DPI_FAC * _style.paneltitle.shady);
+ _style.grouplabel.shadx = (short)(UI_DPI_FAC * _style.grouplabel.shadx);
+ _style.grouplabel.shady = (short)(UI_DPI_FAC * _style.grouplabel.shady);
+ _style.widgetlabel.shadx = (short)(UI_DPI_FAC * _style.widgetlabel.shadx);
+ _style.widgetlabel.shady = (short)(UI_DPI_FAC * _style.widgetlabel.shady);
+
+ _style.columnspace = (short)(UI_DPI_FAC * _style.columnspace);
+ _style.templatespace = (short)(UI_DPI_FAC * _style.templatespace);
+ _style.boxspace = (short)(UI_DPI_FAC * _style.boxspace);
+ _style.buttonspacex = (short)(UI_DPI_FAC * _style.buttonspacex);
+ _style.buttonspacey = (short)(UI_DPI_FAC * _style.buttonspacey);
+ _style.panelspace = (short)(UI_DPI_FAC * _style.panelspace);
+ _style.panelouter = (short)(UI_DPI_FAC * _style.panelouter);
+
+ return &_style;
+}
+
+int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str)
+{
+ int width;
+
+ if (fs->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ UI_fontstyle_set(fs);
+ width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ return width;
+}
+
+int UI_fontstyle_height_max(const uiFontStyle *fs)
+{
+ UI_fontstyle_set(fs);
+ return BLF_height_max(fs->uifont_id);
+}
+
+/* ************** init exit ************************ */
+
+/* called on each startup.blend read */
+/* reading without uifont will create one */
+void uiStyleInit()
+{
+ uiStyle *style = (uiStyle *)U.uistyles.first;
+
+ /* recover from uninitialized dpi */
+ if (U.dpi == 0) {
+ U.dpi = 72;
+ }
+ CLAMP(U.dpi, 48, 144);
+
+ LISTBASE_FOREACH (uiFont *, font, &U.uifonts) {
+ BLF_unload_id(font->blf_id);
+ }
+
+ if (blf_mono_font != -1) {
+ BLF_unload_id(blf_mono_font);
+ blf_mono_font = -1;
+ }
+
+ if (blf_mono_font_render != -1) {
+ BLF_unload_id(blf_mono_font_render);
+ blf_mono_font_render = -1;
+ }
+
+ uiFont *font_first = (uiFont *)U.uifonts.first;
+
+ /* default builtin */
+ if (font_first == NULL) {
+ font_first = (uiFont *)MEM_callocN(sizeof(uiFont), "ui font");
+ BLI_addtail(&U.uifonts, font_first);
+ }
+
+ if (U.font_path_ui[0]) {
+ BLI_strncpy(font_first->filename, U.font_path_ui, sizeof(font_first->filename));
+ font_first->uifont_id = UIFONT_CUSTOM1;
+ }
+ else {
+ BLI_strncpy(font_first->filename, "default", sizeof(font_first->filename));
+ font_first->uifont_id = UIFONT_DEFAULT;
+ }
+
+ LISTBASE_FOREACH (uiFont *, font, &U.uifonts) {
+ const bool unique = false;
+
+ if (font->uifont_id == UIFONT_DEFAULT) {
+ font->blf_id = BLF_load_default(unique);
+ }
+ else {
+ font->blf_id = BLF_load(font->filename);
+ if (font->blf_id == -1) {
+ font->blf_id = BLF_load_default(unique);
+ }
+ }
+
+ BLF_default_set(font->blf_id);
+
+ if (font->blf_id == -1) {
+ if (G.debug & G_DEBUG) {
+ printf("%s: error, no fonts available\n", __func__);
+ }
+ }
+ else {
+ /* ? just for speed to initialize?
+ * Yes, this build the glyph cache and create
+ * the texture.
+ */
+ BLF_size(font->blf_id, 11 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 12 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 14 * U.pixelsize, U.dpi);
+ }
+ }
+
+ if (style == NULL) {
+ ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
+ }
+
+ /* XXX, this should be moved into a style,
+ * but for now best only load the monospaced font once. */
+ BLI_assert(blf_mono_font == -1);
+ /* Use unique font loading to avoid thread safety issues with mono font
+ * used for render metadata stamp in threads. */
+ if (U.font_path_ui_mono[0]) {
+ blf_mono_font = BLF_load_unique(U.font_path_ui_mono);
+ }
+ if (blf_mono_font == -1) {
+ const bool unique = true;
+ blf_mono_font = BLF_load_mono_default(unique);
+ }
+
+ BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
+
+ /* Set default flags based on UI preferences (not render fonts) */
+ {
+ const int flag_disable = (BLF_MONOCHROME | BLF_HINTING_NONE | BLF_HINTING_SLIGHT |
+ BLF_HINTING_FULL);
+ int flag_enable = 0;
+
+ if (U.text_render & USER_TEXT_HINTING_NONE) {
+ flag_enable |= BLF_HINTING_NONE;
+ }
+ else if (U.text_render & USER_TEXT_HINTING_SLIGHT) {
+ flag_enable |= BLF_HINTING_SLIGHT;
+ }
+ else if (U.text_render & USER_TEXT_HINTING_FULL) {
+ flag_enable |= BLF_HINTING_FULL;
+ }
+
+ if (U.text_render & USER_TEXT_DISABLE_AA) {
+ flag_enable |= BLF_MONOCHROME;
+ }
+
+ LISTBASE_FOREACH (uiFont *, font, &U.uifonts) {
+ if (font->blf_id != -1) {
+ BLF_disable(font->blf_id, flag_disable);
+ BLF_enable(font->blf_id, flag_enable);
+ }
+ }
+ if (blf_mono_font != -1) {
+ BLF_disable(blf_mono_font, flag_disable);
+ BLF_enable(blf_mono_font, flag_enable);
+ }
+ }
+
+ /**
+ * Second for rendering else we get threading problems,
+ *
+ * \note This isn't good that the render font depends on the preferences,
+ * keep for now though, since without this there is no way to display many unicode chars.
+ */
+ if (blf_mono_font_render == -1) {
+ const bool unique = true;
+ blf_mono_font_render = BLF_load_mono_default(unique);
+ }
+
+ BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
+}
+
+void UI_fontstyle_set(const uiFontStyle *fs)
+{
+ uiFont *font = uifont_to_blfont(fs->uifont_id);
+
+ BLF_size(font->blf_id, fs->points * U.pixelsize, U.dpi);
+}