Files
test/source/blender/blenkernel/intern/freestyle.cc
Campbell Barton 649b89781e Cleanup: ensure UTF8 string copy for DNA & screen data
Use `BLI_strncpy_utf8` & `BLI_snprintf_utf8` for fixed size buffers in
DNA and screen data structures such as panels, menus & operators.

This could be considered a fix as copying a UTF8 string into a smaller
buffer without proper truncation can create an invalid UTF8 sequence.
However identifying which of these users are likely to run into would
be time consuming and not especially useful.
2025-07-26 12:33:15 +00:00

253 lines
7.2 KiB
C++

/* SPDX-FileCopyrightText: 2013 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include "MEM_guardedalloc.h"
#include "DNA_collection_types.h"
#include "DNA_freestyle_types.h"
#include "BLI_listbase.h"
#include "BLI_math_rotation.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.hh"
#include "BLT_translation.hh"
#include "BKE_freestyle.h"
#include "BKE_lib_id.hh"
#include "BKE_linestyle.h"
/* Function declarations. */
static FreestyleLineSet *alloc_lineset();
static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag);
static FreestyleModuleConfig *alloc_module();
static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module);
void BKE_freestyle_config_init(FreestyleConfig *config)
{
config->mode = FREESTYLE_CONTROL_EDITOR_MODE;
BLI_listbase_clear(&config->modules);
config->flags = 0;
config->sphere_radius = 0.1f;
config->dkr_epsilon = 0.0f;
config->crease_angle = DEG2RADF(134.43f);
BLI_listbase_clear(&config->linesets);
}
void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user)
{
LISTBASE_FOREACH (FreestyleLineSet *, lineset, &config->linesets) {
if (lineset->group) {
if (do_id_user) {
id_us_min(&lineset->group->id);
}
lineset->group = nullptr;
}
if (lineset->linestyle) {
if (do_id_user) {
id_us_min(&lineset->linestyle->id);
}
lineset->linestyle = nullptr;
}
}
BLI_freelistN(&config->linesets);
BLI_freelistN(&config->modules);
}
void BKE_freestyle_config_copy(FreestyleConfig *new_config,
const FreestyleConfig *config,
const int flag)
{
FreestyleLineSet *new_lineset;
FreestyleModuleConfig *new_module;
new_config->mode = config->mode;
new_config->flags = config->flags;
new_config->sphere_radius = config->sphere_radius;
new_config->dkr_epsilon = config->dkr_epsilon;
new_config->crease_angle = config->crease_angle;
BLI_listbase_clear(&new_config->linesets);
LISTBASE_FOREACH (FreestyleLineSet *, lineset, &config->linesets) {
new_lineset = alloc_lineset();
copy_lineset(new_lineset, lineset, flag);
BLI_addtail(&new_config->linesets, (void *)new_lineset);
}
BLI_listbase_clear(&new_config->modules);
LISTBASE_FOREACH (FreestyleModuleConfig *, module, &config->modules) {
new_module = alloc_module();
copy_module(new_module, module);
BLI_addtail(&new_config->modules, (void *)new_module);
}
}
static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag)
{
new_lineset->linestyle = lineset->linestyle;
new_lineset->flags = lineset->flags;
new_lineset->selection = lineset->selection;
new_lineset->qi = lineset->qi;
new_lineset->qi_start = lineset->qi_start;
new_lineset->qi_end = lineset->qi_end;
new_lineset->edge_types = lineset->edge_types;
new_lineset->exclude_edge_types = lineset->exclude_edge_types;
new_lineset->group = lineset->group;
STRNCPY_UTF8(new_lineset->name, lineset->name);
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
id_us_plus((ID *)new_lineset->linestyle);
id_us_plus((ID *)new_lineset->group);
}
}
static FreestyleModuleConfig *alloc_module()
{
return MEM_callocN<FreestyleModuleConfig>("style module configuration");
}
FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config)
{
FreestyleModuleConfig *module_conf = alloc_module();
BLI_addtail(&config->modules, (void *)module_conf);
module_conf->script = nullptr;
module_conf->is_displayed = 1;
return module_conf;
}
static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module)
{
new_module->script = module->script;
new_module->is_displayed = module->is_displayed;
}
bool BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
{
if (BLI_findindex(&config->modules, module_conf) == -1) {
return false;
}
BLI_freelinkN(&config->modules, module_conf);
return true;
}
bool BKE_freestyle_module_move(FreestyleConfig *config,
FreestyleModuleConfig *module_conf,
int direction)
{
return ((BLI_findindex(&config->modules, module_conf) > -1) &&
(BLI_listbase_link_move(&config->modules, module_conf, direction) == true));
}
void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet *lineset)
{
BLI_uniquename(&config->linesets,
lineset,
"FreestyleLineSet",
'.',
offsetof(FreestyleLineSet, name),
sizeof(lineset->name));
}
static FreestyleLineSet *alloc_lineset()
{
return MEM_callocN<FreestyleLineSet>("Freestyle line set");
}
FreestyleLineSet *BKE_freestyle_lineset_add(Main *bmain, FreestyleConfig *config, const char *name)
{
int lineset_index = BLI_listbase_count(&config->linesets);
FreestyleLineSet *lineset = alloc_lineset();
BLI_addtail(&config->linesets, (void *)lineset);
BKE_freestyle_lineset_set_active_index(config, lineset_index);
lineset->linestyle = BKE_linestyle_new(bmain, DATA_("LineStyle"));
lineset->flags |= FREESTYLE_LINESET_ENABLED;
lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES |
FREESTYLE_SEL_IMAGE_BORDER;
lineset->qi = FREESTYLE_QI_VISIBLE;
lineset->qi_start = 0;
lineset->qi_end = 100;
lineset->edge_types = FREESTYLE_FE_SILHOUETTE | FREESTYLE_FE_BORDER | FREESTYLE_FE_CREASE;
lineset->exclude_edge_types = 0;
lineset->group = nullptr;
if (name) {
STRNCPY_UTF8(lineset->name, name);
}
else if (lineset_index > 0) {
SNPRINTF_UTF8(lineset->name, DATA_("LineSet %i"), lineset_index + 1);
}
else {
STRNCPY_UTF8(lineset->name, DATA_("LineSet"));
}
BKE_freestyle_lineset_unique_name(config, lineset);
return lineset;
}
bool BKE_freestyle_lineset_delete(FreestyleConfig *config, FreestyleLineSet *lineset)
{
if (BLI_findindex(&config->linesets, lineset) == -1) {
return false;
}
if (lineset->group) {
id_us_min(&lineset->group->id);
}
if (lineset->linestyle) {
id_us_min(&lineset->linestyle->id);
}
BLI_remlink(&config->linesets, lineset);
MEM_freeN(lineset);
BKE_freestyle_lineset_set_active_index(config, 0);
return true;
}
FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config)
{
LISTBASE_FOREACH (FreestyleLineSet *, lineset, &config->linesets) {
if (lineset->flags & FREESTYLE_LINESET_CURRENT) {
return lineset;
}
}
return nullptr;
}
short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config)
{
FreestyleLineSet *lineset;
short i;
for (lineset = (FreestyleLineSet *)config->linesets.first, i = 0; lineset;
lineset = lineset->next, i++)
{
if (lineset->flags & FREESTYLE_LINESET_CURRENT) {
return i;
}
}
return 0;
}
void BKE_freestyle_lineset_set_active_index(FreestyleConfig *config, short index)
{
FreestyleLineSet *lineset;
short i;
for (lineset = (FreestyleLineSet *)config->linesets.first, i = 0; lineset;
lineset = lineset->next, i++)
{
if (i == index) {
lineset->flags |= FREESTYLE_LINESET_CURRENT;
}
else {
lineset->flags &= ~FREESTYLE_LINESET_CURRENT;
}
}
}