Blender V4.5
vfont.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdio>
10#include <cstdlib>
11#include <cstring>
12#include <cwctype>
13#include <optional>
14
15#include "CLG_log.h"
16
17#include "MEM_guardedalloc.h"
18
19#include "BLI_ghash.h"
20#include "BLI_listbase.h"
21#include "BLI_path_utils.hh"
22#include "BLI_string.h"
23#include "BLI_string_utf8.h"
24#include "BLI_utildefines.h"
25
26#include "BLT_translation.hh"
27
28#include "DNA_curve_types.h"
29#include "DNA_object_types.h"
31#include "DNA_vfont_types.h"
32
33#include "BKE_bpath.hh"
34#include "BKE_curve.hh"
35#include "BKE_global.hh"
36#include "BKE_idtype.hh"
37#include "BKE_lib_id.hh"
38#include "BKE_library.hh"
39#include "BKE_main.hh"
40#include "BKE_packedFile.hh"
41#include "BKE_vfont.hh"
42#include "BKE_vfontdata.hh"
43
44#include "BLO_read_write.hh"
45
46static CLG_LogRef LOG = {"bke.vfont"};
47
48/* -------------------------------------------------------------------- */
51
53
55
56/* -------------------------------------------------------------------- */
59
60const void *builtin_font_data = nullptr;
62
63static void vfont_init_data(ID *id)
64{
65 VFont *vfont = (VFont *)id;
67
68 if (pf) {
69 VFontData *vfd;
70
72 if (vfd) {
73 vfont->data = vfd;
74
76 }
77
78 /* Free the packed file */
80 }
81}
82
83static void vfont_copy_data(Main * /*bmain*/,
84 std::optional<Library *> /*owner_library*/,
85 ID *id_dst,
86 const ID * /*id_src*/,
87 const int flag)
88{
89 VFont *vfont_dst = (VFont *)id_dst;
90
91 /* We never handle user-count here for own data. */
92 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
93
94 /* Just to be sure, should not have any value actually after reading time. */
95 vfont_dst->temp_pf = nullptr;
96
97 if (vfont_dst->packedfile) {
98 vfont_dst->packedfile = BKE_packedfile_duplicate(vfont_dst->packedfile);
99 }
100
101 if (vfont_dst->data) {
102 vfont_dst->data = BKE_vfontdata_copy(vfont_dst->data, flag_subdata);
103 }
104}
105
107static void vfont_free_data(ID *id)
108{
109 VFont *vfont = (VFont *)id;
110 BKE_vfont_data_free(vfont);
111
112 if (vfont->packedfile) {
114 vfont->packedfile = nullptr;
115 }
116}
117
118static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
119{
120 VFont *vfont = (VFont *)id;
121
122 if ((vfont->packedfile != nullptr) &&
123 (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0)
124 {
125 return;
126 }
127
128 if (BKE_vfont_is_builtin(vfont)) {
129 return;
130 }
131
132 BKE_bpath_foreach_path_fixed_process(bpath_data, vfont->filepath, sizeof(vfont->filepath));
133}
134
135static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address)
136{
137 VFont *vf = (VFont *)id;
138 const bool is_undo = BLO_write_is_undo(writer);
139
140 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
141 vf->data = nullptr;
142 vf->temp_pf = nullptr;
143
144 /* Do not store packed files in case this is a library override ID. */
145 if (ID_IS_OVERRIDE_LIBRARY(vf) && !is_undo) {
146 vf->packedfile = nullptr;
147 }
148
149 /* write LibData */
150 BLO_write_id_struct(writer, VFont, id_address, &vf->id);
151 BKE_id_blend_write(writer, &vf->id);
152
153 /* direct data */
155}
156
157static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
158{
159 VFont *vf = (VFont *)id;
160 vf->data = nullptr;
161 vf->temp_pf = nullptr;
163}
164
166 /*id_code*/ VFont::id_type,
167 /*id_filter*/ FILTER_ID_VF,
168 /*dependencies_id_types*/ 0,
169 /*main_listbase_index*/ INDEX_ID_VF,
170 /*struct_size*/ sizeof(VFont),
171 /*name*/ "Font",
172 /*name_plural*/ N_("fonts"),
173 /*translation_context*/ BLT_I18NCONTEXT_ID_VFONT,
175 /*asset_type_info*/ nullptr,
176
177 /*init_data*/ vfont_init_data,
178 /*copy_data*/ vfont_copy_data,
179 /*free_data*/ vfont_free_data,
180 /*make_local*/ nullptr,
181 /*foreach_id*/ nullptr,
182 /*foreach_cache*/ nullptr,
183 /*foreach_path*/ vfont_foreach_path,
184 /*owner_pointer_get*/ nullptr,
185
186 /*blend_write*/ vfont_blend_write,
187 /*blend_read_data*/ vfont_blend_read_data,
188 /*blend_read_after_liblink*/ nullptr,
189
190 /*blend_read_undo_preserve*/ nullptr,
191
192 /*lib_override_apply_post*/ nullptr,
193};
194
196
197/* -------------------------------------------------------------------- */
200
202{
203 PackedFile *pf;
204 if (BKE_vfont_is_builtin(vfont)) {
206 }
207 else {
208 if (vfont->packedfile) {
209 pf = vfont->packedfile;
210
211 /* We need to copy a temporary font to memory unless it is already there. */
212 if (vfont->temp_pf == nullptr) {
214 }
215 }
216 else {
217 pf = BKE_packedfile_new(nullptr, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
218
219 if (vfont->temp_pf == nullptr) {
221 nullptr, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
222 }
223 }
224 if (!pf) {
225 CLOG_WARN(&LOG, "Font file doesn't exist: %s", vfont->filepath);
226
227 /* NOTE(@ideasman42): Don't attempt to find a fallback.
228 * If the font requested by the user doesn't load, font rendering will display
229 * placeholder characters instead. */
230 }
231 }
232
233 if (pf) {
235 if (pf != vfont->packedfile) {
237 }
238 }
239}
240
242{
243 if (vfont->data) {
244 if (vfont->data->characters) {
245 GHashIterator gh_iter;
246 GHASH_ITER (gh_iter, vfont->data->characters) {
247 VChar *che = static_cast<VChar *>(BLI_ghashIterator_getValue(&gh_iter));
248
249 while (che->nurbsbase.first) {
250 Nurb *nu = static_cast<Nurb *>(che->nurbsbase.first);
251 if (nu->bezt) {
252 MEM_freeN(nu->bezt);
253 }
254 BLI_freelinkN(&che->nurbsbase, nu);
255 }
256
257 MEM_freeN(che);
258 }
259
260 BLI_ghash_free(vfont->data->characters, nullptr, nullptr);
261 }
262
263 MEM_freeN(vfont->data);
264 vfont->data = nullptr;
265 }
266
267 if (vfont->temp_pf) {
268 BKE_packedfile_free(vfont->temp_pf); /* Null when the font file can't be found on disk. */
269 vfont->temp_pf = nullptr;
270 }
271}
272
273bool BKE_vfont_is_builtin(const VFont *vfont)
274{
275 return STREQ(vfont->filepath, FO_BUILTIN_NAME);
276}
277
278void BKE_vfont_builtin_register(const void *mem, int size)
279{
280 builtin_font_data = mem;
282}
283
285{
286 if (!builtin_font_data) {
287 CLOG_ERROR(&LOG, "Internal error, builtin font not loaded");
288
289 return nullptr;
290 }
291
292 void *mem = MEM_mallocN(builtin_font_size, "vfd_builtin");
293
295
297}
298
299VFont *BKE_vfont_load(Main *bmain, const char *filepath)
300{
301 char filename[FILE_MAXFILE];
302 VFont *vfont = nullptr;
303 PackedFile *pf;
304 bool is_builtin;
305
306 if (STREQ(filepath, FO_BUILTIN_NAME)) {
307 STRNCPY(filename, filepath);
308
310 is_builtin = true;
311 }
312 else {
313 BLI_path_split_file_part(filepath, filename, sizeof(filename));
314 pf = BKE_packedfile_new(nullptr, filepath, BKE_main_blendfile_path(bmain));
315
316 is_builtin = false;
317 }
318
319 if (pf) {
320 VFontData *vfd;
321
323 if (vfd) {
324 /* If there's a font name, use it for the ID name. */
325 vfont = static_cast<VFont *>(
326 BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0));
327 vfont->data = vfd;
328 STRNCPY(vfont->filepath, filepath);
329
330 /* if auto-pack is on store the packed-file in de font structure */
331 if (!is_builtin && (G.fileflags & G_FILE_AUTOPACK)) {
332 vfont->packedfile = pf;
333 }
334
335 /* Do not add #FO_BUILTIN_NAME to temporary list-base. */
336 if (!STREQ(filename, FO_BUILTIN_NAME)) {
337 vfont->temp_pf = BKE_packedfile_new(nullptr, filepath, BKE_main_blendfile_path(bmain));
338 }
339 }
340
341 /* Free the packed file */
342 if (!vfont || vfont->packedfile != pf) {
344 }
345 }
346
347 return vfont;
348}
349
350VFont *BKE_vfont_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
351{
352 char filepath_abs[FILE_MAX], filepath_test[FILE_MAX];
353
354 STRNCPY(filepath_abs, filepath);
355 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
356
357 /* first search an identical filepath */
358 LISTBASE_FOREACH (VFont *, vfont, &bmain->fonts) {
359 STRNCPY(filepath_test, vfont->filepath);
360 BLI_path_abs(filepath_test, ID_BLEND_PATH(bmain, &vfont->id));
361
362 if (BLI_path_cmp(filepath_test, filepath_abs) == 0) {
363 id_us_plus(&vfont->id); /* officially should not, it doesn't link here! */
364 if (r_exists) {
365 *r_exists = true;
366 }
367 return vfont;
368 }
369 }
370
371 if (r_exists) {
372 *r_exists = false;
373 }
374 return BKE_vfont_load(bmain, filepath);
375}
376
377VFont *BKE_vfont_load_exists(Main *bmain, const char *filepath)
378{
379 return BKE_vfont_load_exists_ex(bmain, filepath, nullptr);
380}
381
383{
384 LISTBASE_FOREACH (VFont *, vfont, &G_MAIN->fonts) {
385 if (BKE_vfont_is_builtin(vfont)) {
386 return vfont;
387 }
388 }
389
390 /* Newly loaded ID's have a user by default, in this case the caller is responsible
391 * for assigning a user, otherwise an additional user would be added, see: #100819. */
393 id_us_min(&vfont->id);
394 BLI_assert(vfont->id.us == 0);
395 return vfont;
396}
397
399
400/* -------------------------------------------------------------------- */
403
404int BKE_vfont_select_get(const Curve *cu, int *r_start, int *r_end)
405{
406 EditFont *ef = cu->editfont;
407 int start, end, direction;
408
409 if (ef == nullptr || (cu->ob_type != OB_FONT)) {
410 return 0;
411 }
412
413 BLI_assert(ef->len >= 0);
414 BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1);
415 BLI_assert(ef->selend >= 0 && ef->selend <= ef->len + 1);
416 BLI_assert(ef->pos >= 0 && ef->pos <= ef->len);
417
418 if (ef->selstart == 0) {
419 return 0;
420 }
421
422 if (ef->selstart <= ef->selend) {
423 start = ef->selstart - 1;
424 end = ef->selend - 1;
425 direction = 1;
426 }
427 else {
428 start = ef->selend;
429 end = ef->selstart - 2;
430 direction = -1;
431 }
432
433 if (start == end + 1) {
434 return 0;
435 }
436
437 BLI_assert(start < end + 1);
438 *r_start = start;
439 *r_end = end;
440 return direction;
441}
442
444{
445 EditFont *ef = cu->editfont;
446
447 BLI_assert((cu->ob_type == OB_FONT) && ef);
448
449 CLAMP_MAX(ef->pos, ef->len);
450 CLAMP_MAX(ef->selstart, ef->len + 1);
451 CLAMP_MAX(ef->selend, ef->len);
452}
453
455
456/* -------------------------------------------------------------------- */
459
460static struct {
461 char32_t *text_buffer;
463 size_t len_utf32;
464 size_t len_utf8;
465} g_vfont_clipboard = {nullptr};
466
468{
469 MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
470 MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
471 g_vfont_clipboard.len_utf32 = 0;
472 g_vfont_clipboard.len_utf8 = 0;
473}
474
475void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, const size_t len)
476{
477 char32_t *text;
478 CharInfo *info;
479
480 /* Clean previous buffers. */
482
483 text = MEM_malloc_arrayN<char32_t>((len + 1), __func__);
484 if (text == nullptr) {
485 return;
486 }
487
488 info = MEM_malloc_arrayN<CharInfo>(len, __func__);
489 if (info == nullptr) {
490 MEM_freeN(text);
491 return;
492 }
493
494 memcpy(text, text_buf, len * sizeof(*text));
495 text[len] = '\0';
496 memcpy(info, info_buf, len * sizeof(CharInfo));
497
498 /* store new buffers */
499 g_vfont_clipboard.text_buffer = text;
500 g_vfont_clipboard.info_buffer = info;
502 g_vfont_clipboard.len_utf32 = len;
503}
504
505void BKE_vfont_clipboard_get(char32_t **r_text_buf,
506 CharInfo **r_info_buf,
507 size_t *r_len_utf8,
508 size_t *r_len_utf32)
509{
510 if (r_text_buf) {
511 *r_text_buf = g_vfont_clipboard.text_buffer;
512 }
513
514 if (r_info_buf) {
515 *r_info_buf = g_vfont_clipboard.info_buffer;
516 }
517
518 if (r_len_utf32) {
519 *r_len_utf32 = g_vfont_clipboard.len_utf32;
520 }
521
522 if (r_len_utf8) {
523 *r_len_utf8 = g_vfont_clipboard.len_utf8;
524 }
525}
526
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:125
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
Definition BKE_bpath.hh:37
#define G_MAIN
@ G_FILE_AUTOPACK
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:44
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:46
IDTypeInfo IDType_ID_VF
Definition vfont.cc:165
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1428
void id_us_plus(ID *id)
Definition lib_id.cc:353
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void id_us_min(ID *id)
Definition lib_id.cc:361
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:872
PackedFile * BKE_packedfile_duplicate(const PackedFile *pf_src)
void BKE_packedfile_free(PackedFile *pf)
PackedFile * BKE_packedfile_new_from_memory(const void *mem, int memlen, const blender::ImplicitSharingInfo *sharing_info=nullptr)
void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf)
void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p, blender::StringRefNull filepath)
PackedFile * BKE_packedfile_new(ReportList *reports, const char *filepath_rel, const char *basepath)
A structure to represent vector fonts, and to load them from PostScript fonts.
VFontData * BKE_vfontdata_copy(const VFontData *vfont_src, int flag)
VFontData * BKE_vfontdata_from_freetypefont(PackedFile *pf)
#define BLI_assert(a)
Definition BLI_assert.h:46
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
#define GHASH_ITER(gh_iter_, ghash_)
Definition BLI_ghash.h:318
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAXFILE
#define FILE_MAX
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
#define BLI_path_cmp
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define CLAMP_MAX(a, c)
#define STREQ(a, b)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLT_I18NCONTEXT_ID_VFONT
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
@ INDEX_ID_VF
Definition DNA_ID.h:1209
@ ID_VF
Object is a sort of wrapper for general info.
@ OB_FONT
#define FO_BUILTIN_NAME
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define pf(_x, _i)
Prefetch 64.
Definition gim_memory.h:48
#define MEM_SAFE_FREE(v)
#define FILTER_ID_VF
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
#define ID_BLEND_PATH(_bmain, _id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define LOG(severity)
Definition log.h:32
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
eBPathForeachFlag flag
Definition BKE_bpath.hh:94
struct EditFont * editfont
short ob_type
int selend
Definition BKE_vfont.hh:60
int selstart
Definition BKE_vfont.hh:60
Definition DNA_ID.h:404
int us
Definition DNA_ID.h:425
void * first
ListBase fonts
Definition BKE_main.hh:262
BezTriple * bezt
ListBase nurbsbase
GHash * characters
char name[128]
struct VFontData * data
char filepath[1024]
struct PackedFile * temp_pf
struct PackedFile * packedfile
uint len
#define N_(msgid)
void BKE_vfont_data_ensure(VFont *vfont)
Definition vfont.cc:201
int BKE_vfont_select_get(const Curve *cu, int *r_start, int *r_end)
Definition vfont.cc:404
static void vfont_init_data(ID *id)
Definition vfont.cc:63
void BKE_vfont_data_free(VFont *vfont)
Definition vfont.cc:241
static PackedFile * packedfile_new_from_builtin()
Definition vfont.cc:284
CharInfo * info_buffer
Definition vfont.cc:462
int builtin_font_size
Definition vfont.cc:61
VFont * BKE_vfont_load(Main *bmain, const char *filepath)
Definition vfont.cc:299
static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
Definition vfont.cc:157
bool BKE_vfont_is_builtin(const VFont *vfont)
Definition vfont.cc:273
const void * builtin_font_data
Definition vfont.cc:60
static void vfont_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *, const int flag)
Definition vfont.cc:83
static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition vfont.cc:118
void BKE_vfont_select_clamp(Curve *cu)
Definition vfont.cc:443
VFont * BKE_vfont_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
Definition vfont.cc:350
char32_t * text_buffer
Definition vfont.cc:461
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, const size_t len)
Definition vfont.cc:475
static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition vfont.cc:135
VFont * BKE_vfont_load_exists(Main *bmain, const char *filepath)
Definition vfont.cc:377
static struct @042350060317054144152267333223132146302260006157 g_vfont_clipboard
void BKE_vfont_builtin_register(const void *mem, int size)
Definition vfont.cc:278
void BKE_vfont_clipboard_get(char32_t **r_text_buf, CharInfo **r_info_buf, size_t *r_len_utf8, size_t *r_len_utf32)
Definition vfont.cc:505
VFont * BKE_vfont_builtin_ensure()
Definition vfont.cc:382
size_t len_utf32
Definition vfont.cc:463
static void vfont_free_data(ID *id)
Definition vfont.cc:107
size_t len_utf8
Definition vfont.cc:464
void BKE_vfont_clipboard_free()
Definition vfont.cc:467
uint8_t flag
Definition wm_window.cc:139