This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenkernel/intern/font.c

1400 lines
33 KiB
C
Raw Normal View History

2011-10-10 09:38:02 +00:00
/*
* ***** BEGIN GPL LICENSE BLOCK *****
2002-10-12 11:37:38 +00:00
*
* 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.
2002-10-12 11:37:38 +00:00
*
* 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,
2010-02-12 13:34:04 +00:00
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2002-10-12 11:37:38 +00:00
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
2002-10-12 11:37:38 +00:00
*/
2011-02-27 20:40:57 +00:00
/** \file blender/blenkernel/intern/font.c
* \ingroup bke
*/
2002-10-12 11:37:38 +00:00
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
2002-10-12 11:37:38 +00:00
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLI_listbase.h"
#include "BLI_ghash.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_math.h"
#include "BLI_threads.h"
2002-10-12 11:37:38 +00:00
#include "BLI_vfontdata.h"
#include "DNA_packedFile_types.h"
#include "DNA_curve_types.h"
#include "DNA_vfont_types.h"
#include "DNA_object_types.h"
2002-10-12 11:37:38 +00:00
#include "BKE_packedFile.h"
#include "BKE_library.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_anim.h"
#include "BKE_curve.h"
static ThreadRWMutex vfont_rwlock = BLI_RWLOCK_INITIALIZER;
/* The vfont code */
void BKE_vfont_free_data(struct VFont *vfont)
{
if (vfont->data) {
if (vfont->data->characters) {
GHashIterator gh_iter;
GHASH_ITER (gh_iter, vfont->data->characters) {
VChar *che = BLI_ghashIterator_getValue(&gh_iter);
while (che->nurbsbase.first) {
Nurb *nu = che->nurbsbase.first;
if (nu->bezt) MEM_freeN(nu->bezt);
BLI_freelinkN(&che->nurbsbase, nu);
}
MEM_freeN(che);
2002-10-12 11:37:38 +00:00
}
BLI_ghash_free(vfont->data->characters, NULL, NULL);
2002-10-12 11:37:38 +00:00
}
MEM_freeN(vfont->data);
vfont->data = NULL;
2002-10-12 11:37:38 +00:00
}
if (vfont->temp_pf) {
freePackedFile(vfont->temp_pf); /* NULL when the font file can't be found on disk */
vfont->temp_pf = NULL;
}
}
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling). This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock was pretty much impossible, except for a few special cases. Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite a few ID usages were missed or wrongly handled that way). One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling by using library_query utils to allow generic handling of those, which is now the case (now, generic ID links handling is only "knwon" from readfile.c and library_query.c). This commit also adds backends to allow live replacement and deletion of datablocks in Blender (so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one, or NULL one in case of unlinking). This will allow nice new features, like ability to easily reload or relocate libraries, real immediate deletion of datablocks in blender, replacement of one datablock by another, etc. Some of those are for next commits. A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core. Though it was tested rather deeply, being totally impossible to check all possible ID usage cases, it's likely there are some remaining issues and bugs in new code... Please report them! ;) Review task: D2027 (https://developer.blender.org/D2027). Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
/** Free (or release) any data used by this font (does not free the font itself). */
void BKE_vfont_free(struct VFont *vf)
{
BKE_vfont_free_data(vf);
2002-10-12 11:37:38 +00:00
if (vf->packedfile) {
freePackedFile(vf->packedfile);
vf->packedfile = NULL;
}
}
static void *builtin_font_data = NULL;
static int builtin_font_size = 0;
2002-10-12 11:37:38 +00:00
2013-03-09 05:35:49 +00:00
bool BKE_vfont_is_builtin(struct VFont *vfont)
{
return STREQ(vfont->name, FO_BUILTIN_NAME);
}
void BKE_vfont_builtin_register(void *mem, int size)
2002-10-12 11:37:38 +00:00
{
builtin_font_data = mem;
builtin_font_size = size;
2002-10-12 11:37:38 +00:00
}
static PackedFile *get_builtin_packedfile(void)
{
if (!builtin_font_data) {
printf("Internal error, builtin font not loaded\n");
2002-10-12 11:37:38 +00:00
return NULL;
}
else {
void *mem = MEM_mallocN(builtin_font_size, "vfd_builtin");
2002-10-12 11:37:38 +00:00
memcpy(mem, builtin_font_data, builtin_font_size);
return newPackedFileMemory(mem, builtin_font_size);
}
}
static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
{
if (vfont == NULL) {
return NULL;
}
2012-07-07 22:51:57 +00:00
/* And then set the data */
2002-10-12 11:37:38 +00:00
if (!vfont->data) {
PackedFile *pf;
2012-07-07 22:51:57 +00:00
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_WRITE);
if (vfont->data) {
/* Check data again, since it might have been already
* initialized from other thread (previous check is
* not accurate or threading, just prevents unneeded
* lock if all the data is here for sure).
*/
BLI_rw_mutex_unlock(&vfont_rwlock);
return vfont->data;
}
if (BKE_vfont_is_builtin(vfont)) {
pf = get_builtin_packedfile();
}
else {
2002-10-12 11:37:38 +00:00
if (vfont->packedfile) {
pf = vfont->packedfile;
2012-07-07 22:51:57 +00:00
/* We need to copy a tmp font to memory unless it is already there */
if (vfont->temp_pf == NULL) {
vfont->temp_pf = dupPackedFile(pf);
}
}
else {
pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
if (vfont->temp_pf == NULL) {
vfont->temp_pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
}
2002-10-12 11:37:38 +00:00
}
if (!pf) {
printf("Font file doesn't exist: %s\n", vfont->name);
/* DON'T DO THIS
2014-01-17 17:35:03 +11:00
* missing file shouldn't modify path! - campbell */
#if 0
strcpy(vfont->name, FO_BUILTIN_NAME);
#endif
pf = get_builtin_packedfile();
}
2002-10-12 11:37:38 +00:00
}
if (pf) {
vfont->data = BLI_vfontdata_from_freetypefont(pf);
2002-10-12 11:37:38 +00:00
if (pf != vfont->packedfile) {
freePackedFile(pf);
}
}
BLI_rw_mutex_unlock(&vfont_rwlock);
2002-10-12 11:37:38 +00:00
}
return vfont->data;
2002-10-12 11:37:38 +00:00
}
/* Bad naming actually in this case... */
void BKE_vfont_init(VFont *vfont)
{
PackedFile *pf = get_builtin_packedfile();
if (pf) {
VFontData *vfd;
vfd = BLI_vfontdata_from_freetypefont(pf);
if (vfd) {
vfont->data = vfd;
BLI_strncpy(vfont->name, FO_BUILTIN_NAME, sizeof(vfont->name));
}
/* Free the packed file */
freePackedFile(pf);
}
}
VFont *BKE_vfont_load(Main *bmain, const char *filepath)
2002-10-12 11:37:38 +00:00
{
char filename[FILE_MAXFILE];
VFont *vfont = NULL;
2002-10-12 11:37:38 +00:00
PackedFile *pf;
PackedFile *temp_pf = NULL;
2014-02-03 18:55:59 +11:00
bool is_builtin;
2002-10-12 11:37:38 +00:00
if (STREQ(filepath, FO_BUILTIN_NAME)) {
BLI_strncpy(filename, filepath, sizeof(filename));
2002-10-12 11:37:38 +00:00
pf = get_builtin_packedfile();
is_builtin = true;
}
else {
BLI_split_file_part(filepath, filename, sizeof(filename));
pf = newPackedFile(NULL, filepath, bmain->name);
temp_pf = newPackedFile(NULL, filepath, bmain->name);
is_builtin = false;
2002-10-12 11:37:38 +00:00
}
if (pf) {
VFontData *vfd;
vfd = BLI_vfontdata_from_freetypefont(pf);
2002-10-12 11:37:38 +00:00
if (vfd) {
vfont = BKE_libblock_alloc(bmain, ID_VF, filename);
2002-10-12 11:37:38 +00:00
vfont->data = vfd;
/* if there's a font name, use it for the ID name */
if (vfd->name[0] != '\0') {
BLI_strncpy(vfont->id.name + 2, vfd->name, sizeof(vfont->id.name) - 2);
}
BLI_strncpy(vfont->name, filepath, sizeof(vfont->name));
2002-10-12 11:37:38 +00:00
2012-07-07 22:51:57 +00:00
/* if autopack is on store the packedfile in de font structure */
2002-10-12 11:37:38 +00:00
if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
vfont->packedfile = pf;
}
2012-07-07 22:51:57 +00:00
/* Do not add FO_BUILTIN_NAME to temporary listbase */
if (!STREQ(filename, FO_BUILTIN_NAME)) {
vfont->temp_pf = temp_pf;
2012-07-07 22:51:57 +00:00
}
2002-10-12 11:37:38 +00:00
}
2012-07-07 22:51:57 +00:00
/* Free the packed file */
2002-10-12 11:37:38 +00:00
if (!vfont || vfont->packedfile != pf) {
freePackedFile(pf);
}
}
return vfont;
}
VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists)
{
VFont *vfont;
char str[FILE_MAX], strtest[FILE_MAX];
BLI_strncpy(str, filepath, sizeof(str));
BLI_path_abs(str, bmain->name);
/* first search an identical filepath */
for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) {
BLI_strncpy(strtest, vfont->name, sizeof(vfont->name));
BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &vfont->id));
if (BLI_path_cmp(strtest, str) == 0) {
id_us_plus(&vfont->id); /* officially should not, it doesn't link here! */
if (r_exists)
*r_exists = true;
return vfont;
}
}
if (r_exists)
*r_exists = false;
return BKE_vfont_load(bmain, filepath);
}
VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath)
{
return BKE_vfont_load_exists_ex(bmain, filepath, NULL);
}
void BKE_vfont_make_local(Main *bmain, VFont *vfont, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &vfont->id, true, lib_local);
}
static VFont *which_vfont(Curve *cu, CharInfo *info)
{
switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {
case CU_CHINFO_BOLD:
return cu->vfontb ? cu->vfontb : cu->vfont;
case CU_CHINFO_ITALIC:
return cu->vfonti ? cu->vfonti : cu->vfont;
case (CU_CHINFO_BOLD | CU_CHINFO_ITALIC):
return cu->vfontbi ? cu->vfontbi : cu->vfont;
default:
return cu->vfont;
}
}
VFont *BKE_vfont_builtin_get(void)
{
VFont *vfont;
for (vfont = G.main->vfont.first; vfont; vfont = vfont->id.next) {
if (BKE_vfont_is_builtin(vfont)) {
return vfont;
}
}
return BKE_vfont_load(G.main, FO_BUILTIN_NAME);
}
static VChar *find_vfont_char(VFontData *vfd, unsigned int character)
{
return BLI_ghash_lookup(vfd->characters, SET_UINT_IN_POINTER(character));
}
static void build_underline(Curve *cu, ListBase *nubase, const rctf *rect,
float yofs, float rot, int charidx, short mat_nr)
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
{
Nurb *nu2;
BPoint *bp;
nu2 = (Nurb *) MEM_callocN(sizeof(Nurb), "underline_nurb");
nu2->resolu = cu->resolu;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
nu2->bezt = NULL;
nu2->knotsu = nu2->knotsv = NULL;
nu2->flag = CU_2D;
nu2->charidx = charidx + 1000;
if (mat_nr > 0) nu2->mat_nr = mat_nr - 1;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
nu2->pntsu = 4;
nu2->pntsv = 1;
nu2->orderu = 4;
nu2->orderv = 1;
nu2->flagu = CU_NURB_CYCLIC;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
bp = (BPoint *)MEM_callocN(4 * sizeof(BPoint), "underline_bp");
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
copy_v4_fl4(bp[0].vec, rect->xmin, (rect->ymax + yofs), 0.0f, 1.0f);
copy_v4_fl4(bp[1].vec, rect->xmax, (rect->ymax + yofs), 0.0f, 1.0f);
copy_v4_fl4(bp[2].vec, rect->xmax, (rect->ymin + yofs), 0.0f, 1.0f);
copy_v4_fl4(bp[3].vec, rect->xmin, (rect->ymin + yofs), 0.0f, 1.0f);
nu2->bp = bp;
BLI_addtail(nubase, nu2);
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
if (rot != 0.0f) {
float si, co;
int i;
si = sinf(rot);
co = cosf(rot);
for (i = nu2->pntsu; i > 0; i--) {
float *fp;
float x, y;
fp = bp->vec;
x = fp[0] - rect->xmin;
y = fp[1] - rect->ymin;
fp[0] = (+co * x + si * y) + rect->xmin;
fp[1] = (-si * x + co * y) + rect->ymin;
bp++;
}
2014-01-08 00:57:30 +11:00
bp = nu2->bp;
}
mul_v2_fl(bp[0].vec, cu->fsize);
mul_v2_fl(bp[1].vec, cu->fsize);
mul_v2_fl(bp[2].vec, cu->fsize);
mul_v2_fl(bp[3].vec, cu->fsize);
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
}
static void buildchar(Main *bmain, Curve *cu, ListBase *nubase, unsigned int character, CharInfo *info,
2012-08-04 19:34:38 +00:00
float ofsx, float ofsy, float rot, int charidx)
2002-10-12 11:37:38 +00:00
{
BezTriple *bezt1, *bezt2;
Nurb *nu1 = NULL, *nu2 = NULL;
2002-10-12 11:37:38 +00:00
float *fp, fsize, shear, x, si, co;
VFontData *vfd = NULL;
VChar *che = NULL;
int i;
2002-10-12 11:37:38 +00:00
vfd = vfont_get_data(bmain, which_vfont(cu, info));
2002-10-12 11:37:38 +00:00
if (!vfd) return;
#if 0
if (cu->selend < cu->selstart) {
if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart - 2)))
sel = 1;
}
else {
if ((charidx >= (cu->selstart - 1)) && (charidx <= (cu->selend - 1)))
sel = 1;
}
#endif
/* make a copy at distance ofsx, ofsy with shear */
fsize = cu->fsize;
shear = cu->shear;
2012-08-04 19:34:38 +00:00
si = sinf(rot);
co = cosf(rot);
2002-10-12 11:37:38 +00:00
che = find_vfont_char(vfd, character);
2012-07-07 22:51:57 +00:00
/* Select the glyph data */
if (che)
nu1 = che->nurbsbase.first;
2012-07-07 22:51:57 +00:00
/* Create the character */
while (nu1) {
2002-10-12 11:37:38 +00:00
bezt1 = nu1->bezt;
2012-02-27 10:35:39 +00:00
if (bezt1) {
nu2 = (Nurb *) MEM_mallocN(sizeof(Nurb), "duplichar_nurb");
if (nu2 == NULL) break;
2002-10-12 11:37:38 +00:00
memcpy(nu2, nu1, sizeof(struct Nurb));
nu2->resolu = cu->resolu;
nu2->bp = NULL;
nu2->knotsu = nu2->knotsv = NULL;
nu2->flag = CU_SMOOTH;
nu2->charidx = charidx;
if (info->mat_nr > 0) {
nu2->mat_nr = info->mat_nr - 1;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
}
else {
nu2->mat_nr = 0;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
}
2002-10-12 11:37:38 +00:00
/* nu2->trim.first = 0; */
/* nu2->trim.last = 0; */
i = nu2->pntsu;
bezt2 = (BezTriple *)MEM_mallocN(i * sizeof(BezTriple), "duplichar_bezt2");
2012-02-27 10:35:39 +00:00
if (bezt2 == NULL) {
2002-10-12 11:37:38 +00:00
MEM_freeN(nu2);
break;
}
memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
nu2->bezt = bezt2;
if (shear != 0.0f) {
2002-10-12 11:37:38 +00:00
bezt2 = nu2->bezt;
for (i = nu2->pntsu; i > 0; i--) {
2002-10-12 11:37:38 +00:00
bezt2->vec[0][0] += shear * bezt2->vec[0][1];
bezt2->vec[1][0] += shear * bezt2->vec[1][1];
bezt2->vec[2][0] += shear * bezt2->vec[2][1];
bezt2++;
}
}
if (rot != 0.0f) {
bezt2 = nu2->bezt;
for (i = nu2->pntsu; i > 0; i--) {
fp = bezt2->vec[0];
x = fp[0];
fp[0] = co * x + si * fp[1];
fp[1] = -si * x + co * fp[1];
x = fp[3];
fp[3] = co * x + si * fp[4];
fp[4] = -si * x + co * fp[4];
x = fp[6];
fp[6] = co * x + si * fp[7];
fp[7] = -si * x + co * fp[7];
2002-10-12 11:37:38 +00:00
bezt2++;
}
}
bezt2 = nu2->bezt;
if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
const float sca = cu->smallcaps_scale;
for (i = nu2->pntsu; i > 0; i--) {
fp = bezt2->vec[0];
fp[0] *= sca;
fp[1] *= sca;
fp[3] *= sca;
fp[4] *= sca;
fp[6] *= sca;
fp[7] *= sca;
bezt2++;
}
}
bezt2 = nu2->bezt;
for (i = nu2->pntsu; i > 0; i--) {
fp = bezt2->vec[0];
fp[0] = (fp[0] + ofsx) * fsize;
fp[1] = (fp[1] + ofsy) * fsize;
fp[3] = (fp[3] + ofsx) * fsize;
fp[4] = (fp[4] + ofsy) * fsize;
fp[6] = (fp[6] + ofsx) * fsize;
fp[7] = (fp[7] + ofsy) * fsize;
2002-10-12 11:37:38 +00:00
bezt2++;
}
BLI_addtail(nubase, nu2);
2002-10-12 11:37:38 +00:00
}
2002-10-12 11:37:38 +00:00
nu1 = nu1->next;
}
}
int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
{
Curve *cu = ob->data;
EditFont *ef = cu->editfont;
int start, end, direction;
if ((ob->type != OB_FONT) || (ef == NULL)) return 0;
BLI_assert(ef->len >= 0);
BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1);
2016-06-08 16:31:40 +10:00
BLI_assert(ef->selend >= 0 && ef->selend <= ef->len + 1);
BLI_assert(ef->pos >= 0 && ef->pos <= ef->len);
if (ef->selstart == 0) {
return 0;
}
if (ef->selstart <= ef->selend) {
start = ef->selstart - 1;
end = ef->selend - 1;
direction = 1;
}
else {
start = ef->selend;
end = ef->selstart - 2;
direction = -1;
}
if (start == end + 1) {
return 0;
}
else {
BLI_assert(start < end + 1);
*r_start = start;
*r_end = end;
return direction;
}
}
void BKE_vfont_select_clamp(Object *ob)
{
Curve *cu = ob->data;
EditFont *ef = cu->editfont;
BLI_assert((ob->type == OB_FONT) && ef);
CLAMP_MAX(ef->pos, ef->len);
CLAMP_MAX(ef->selstart, ef->len + 1);
CLAMP_MAX(ef->selend, ef->len);
}
2002-10-12 11:37:38 +00:00
static float char_width(Curve *cu, VChar *che, CharInfo *info)
{
2012-07-07 22:51:57 +00:00
/* The character wasn't found, propably ascii = 0, then the width shall be 0 as well */
if (che == NULL) {
return 0.0f;
}
else if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
return che->width * cu->smallcaps_scale;
}
else {
return che->width;
}
}
static void textbox_scale(TextBox *tb_dst, const TextBox *tb_src, float scale)
{
tb_dst->x = tb_src->x * scale;
tb_dst->y = tb_src->y * scale;
tb_dst->w = tb_src->w * scale;
tb_dst->h = tb_src->h * scale;
}
/**
* Used for storing per-line data for alignment & wrapping.
*/
struct TempLineInfo {
float x_min; /* left margin */
float x_max; /* right margin */
int char_nr; /* number of characters */
int wspace_nr; /* number of whitespaces of line */
};
bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase,
const wchar_t **r_text, int *r_text_len, bool *r_text_free,
struct CharTrans **r_chartransdata)
2012-05-17 23:21:11 +00:00
{
Curve *cu = ob->data;
EditFont *ef = cu->editfont;
EditFontSelBox *selboxes = NULL;
VFont *vfont, *oldvfont;
VFontData *vfd = NULL;
2010-12-31 20:01:38 +00:00
CharInfo *info = NULL, *custrinfo;
TextBox tb_scale;
bool use_textbox;
VChar *che;
struct CharTrans *chartransdata = NULL, *ct;
/* Text at the beginning of the last used text-box (use for y-axis alignment). */
int i_textbox = 0;
struct TempLineInfo *lineinfo;
float *f, xof, yof, xtrax, linedist;
float twidth, maxlen = 0;
int i, slen, j;
int curbox;
int selstart, selend;
int cnr = 0, lnr = 0, wsnr = 0;
const wchar_t *mem;
wchar_t ascii;
bool ok = false;
const float xof_scale = cu->xof / cu->fsize;
const float yof_scale = cu->yof / cu->fsize;
#define MARGIN_X_MIN (xof_scale + tb_scale.x)
#define MARGIN_Y_MIN (yof_scale + tb_scale.y)
2002-10-12 11:37:38 +00:00
2012-08-04 19:34:38 +00:00
/* remark: do calculations including the trailing '\0' of a string
* because the cursor can be at that location */
2002-10-12 11:37:38 +00:00
BLI_assert(ob->type == OB_FONT);
2002-10-12 11:37:38 +00:00
2012-07-07 22:51:57 +00:00
/* Set font data */
vfont = cu->vfont;
2012-07-07 22:51:57 +00:00
if (cu->str == NULL) return ok;
if (vfont == NULL) return ok;
vfd = vfont_get_data(bmain, vfont);
2012-07-07 22:51:57 +00:00
/* The VFont Data can not be found */
if (!vfd) return ok;
if (ef) {
slen = ef->len;
mem = ef->textbuf;
custrinfo = ef->textbufinfo;
}
else {
wchar_t *mem_tmp;
slen = cu->len_wchar;
/* Create unicode string */
mem_tmp = MEM_mallocN(((slen + 1) * sizeof(wchar_t)), "convertedmem");
BLI_strncpy_wchar_from_utf8(mem_tmp, cu->str, slen + 1);
if (cu->strinfo == NULL) { /* old file */
cu->strinfo = MEM_callocN((slen + 4) * sizeof(CharInfo), "strinfo compat");
}
custrinfo = cu->strinfo;
mem = mem_tmp;
}
if (cu->tb == NULL)
cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "TextBox compat");
if (ef) {
if (ef->selboxes)
MEM_freeN(ef->selboxes);
if (BKE_vfont_select_get(ob, &selstart, &selend))
ef->selboxes = MEM_callocN((selend - selstart + 1) * sizeof(EditFontSelBox), "font selboxes");
else
ef->selboxes = NULL;
selboxes = ef->selboxes;
}
/* calc offset and rotation of each char */
ct = chartransdata = MEM_callocN((slen + 1) * sizeof(struct CharTrans), "buildtext");
2002-10-12 11:37:38 +00:00
/* We assume the worst case: 1 character per line (is freed at end anyway) */
lineinfo = MEM_mallocN(sizeof(*lineinfo) * (slen * 2 + 1), "lineinfo");
linedist = cu->linedist;
curbox = 0;
textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / cu->fsize);
use_textbox = (tb_scale.w != 0.0f);
xof = MARGIN_X_MIN;
yof = MARGIN_Y_MIN;
xtrax = 0.5f * cu->spacing - 0.5f;
oldvfont = NULL;
for (i = 0; i < slen; i++) {
custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK);
}
2002-10-12 11:37:38 +00:00
for (i = 0; i <= slen; i++) {
makebreak:
2012-07-07 22:51:57 +00:00
/* Characters in the list */
info = &custrinfo[i];
ascii = mem[i];
if (info->flag & CU_CHINFO_SMALLCAPS) {
ascii = towupper(ascii);
if (mem[i] != ascii) {
info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
}
}
vfont = which_vfont(cu, info);
if (vfont == NULL) break;
if (vfont != oldvfont) {
vfd = vfont_get_data(bmain, vfont);
oldvfont = vfont;
}
/* VFont Data for VFont couldn't be found */
if (!vfd) {
MEM_freeN(chartransdata);
chartransdata = NULL;
MEM_freeN(lineinfo);
goto finally;
}
if (!ELEM(ascii, '\n', '\0')) {
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_READ);
che = find_vfont_char(vfd, ascii);
BLI_rw_mutex_unlock(&vfont_rwlock);
/*
* The character wasn't in the current curve base so load it
* But if the font is built-in then do not try loading since
* whole font is in the memory already
*/
if (che == NULL && BKE_vfont_is_builtin(vfont) == false) {
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_WRITE);
/* Check it once again, char might have been already load
* between previous BLI_rw_mutex_unlock() and this BLI_rw_mutex_lock().
*
* Such a check should not be a bottleneck since it wouldn't
* happen often once all the chars are load.
*/
if ((che = find_vfont_char(vfd, ascii)) == NULL) {
che = BLI_vfontchar_from_freetypefont(vfont, ascii);
}
BLI_rw_mutex_unlock(&vfont_rwlock);
}
}
else {
che = NULL;
}
twidth = char_width(cu, che, info);
2012-07-07 22:51:57 +00:00
/* Calculate positions */
if ((tb_scale.w != 0.0f) &&
2012-08-04 19:34:38 +00:00
(ct->dobreak == 0) &&
(((xof - tb_scale.x) + twidth) > xof_scale + tb_scale.w))
2012-08-04 19:34:38 +00:00
{
// fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
if (mem[j] == ' ' || mem[j] == '-') {
ct -= (i - (j - 1));
cnr -= (i - (j - 1));
if (mem[j] == ' ') wsnr--;
if (mem[j] == '-') wsnr++;
i = j - 1;
xof = ct->xof;
ct[1].dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
goto makebreak;
}
if (chartransdata[j].dobreak) {
// fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
ct->dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
ct -= 1;
cnr -= 1;
i--;
xof = ct->xof;
goto makebreak;
}
}
}
2012-08-04 19:34:38 +00:00
if (ascii == '\n' || ascii == 0 || ct->dobreak) {
ct->xof = xof;
ct->yof = yof;
ct->linenr = lnr;
ct->charnr = cnr;
yof -= linedist;
lineinfo[lnr].x_min = (xof - xtrax) - tb_scale.x;
lineinfo[lnr].x_max = tb_scale.w;
lineinfo[lnr].char_nr = cnr;
lineinfo[lnr].wspace_nr = wsnr;
CLAMP_MIN(maxlen, lineinfo[lnr].x_min);
if ((tb_scale.h != 0.0f) &&
(cu->totbox > (curbox + 1)) &&
((-(yof - tb_scale.y)) > (tb_scale.h - linedist) - yof_scale))
{
i_textbox = i + 1;
maxlen = 0;
curbox++;
textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / cu->fsize);
yof = MARGIN_Y_MIN;
}
2011-01-08 12:43:44 +00:00
/* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
#if 0
if (ascii == '\n')
xof = xof_scale;
else
xof = MARGIN_X_MIN;
2011-01-08 12:43:44 +00:00
#else
xof = MARGIN_X_MIN;
2011-01-08 12:43:44 +00:00
#endif
2002-10-12 11:37:38 +00:00
lnr++;
cnr = 0;
wsnr = 0;
2002-10-12 11:37:38 +00:00
}
else if (ascii == 9) { /* TAB */
float tabfac;
ct->xof = xof;
ct->yof = yof;
ct->linenr = lnr;
ct->charnr = cnr++;
tabfac = (xof - MARGIN_X_MIN + 0.01f);
tabfac = 2.0f * ceilf(tabfac / 2.0f);
xof = MARGIN_X_MIN + tabfac;
2002-10-12 11:37:38 +00:00
}
else {
EditFontSelBox *sb = NULL;
float wsfac;
ct->xof = xof;
ct->yof = yof;
ct->linenr = lnr;
ct->charnr = cnr++;
2002-10-12 11:37:38 +00:00
if (selboxes && (i >= selstart) && (i <= selend)) {
sb = &selboxes[i - selstart];
sb->y = yof * cu->fsize - linedist * cu->fsize * 0.1f;
sb->h = linedist * cu->fsize;
sb->w = xof * cu->fsize;
}
if (ascii == 32) {
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
wsfac = cu->wordspace;
wsnr++;
}
2012-08-04 19:34:38 +00:00
else {
wsfac = 1.0f;
}
2012-07-07 22:51:57 +00:00
/* Set the width of the character */
twidth = char_width(cu, che, info);
xof += (twidth * wsfac * (1.0f + (info->kern / 40.0f)) ) + xtrax;
2012-08-04 19:34:38 +00:00
if (sb) {
sb->w = (xof * cu->fsize) - sb->w;
2012-08-04 19:34:38 +00:00
}
2002-10-12 11:37:38 +00:00
}
ct++;
}
cu->lines = 1;
for (i = 0; i <= slen; i++) {
ascii = mem[i];
ct = &chartransdata[i];
if (ascii == '\n' || ct->dobreak) cu->lines++;
}
/* linedata is now: width of line */
2016-06-21 12:44:49 +10:00
if (cu->spacemode != CU_ALIGN_X_LEFT) {
ct = chartransdata;
2002-10-12 11:37:38 +00:00
2016-06-21 12:44:49 +10:00
if (cu->spacemode == CU_ALIGN_X_RIGHT) {
struct TempLineInfo *li;
for (i = 0, li = lineinfo; i < lnr; i++, li++) {
li->x_min = (li->x_max - li->x_min) + xof_scale;
}
for (i = 0; i <= slen; i++) {
ct->xof += lineinfo[ct->linenr].x_min;
2002-10-12 11:37:38 +00:00
ct++;
}
}
2016-06-21 12:44:49 +10:00
else if (cu->spacemode == CU_ALIGN_X_MIDDLE) {
struct TempLineInfo *li;
for (i = 0, li = lineinfo; i < lnr; i++, li++) {
li->x_min = ((li->x_max - li->x_min) + xof_scale) / 2.0f;
}
for (i = 0; i <= slen; i++) {
ct->xof += lineinfo[ct->linenr].x_min;
2002-10-12 11:37:38 +00:00
ct++;
}
}
2016-06-21 12:44:49 +10:00
else if ((cu->spacemode == CU_ALIGN_X_FLUSH) && use_textbox) {
struct TempLineInfo *li;
for (i = 0, li = lineinfo; i < lnr; i++, li++) {
li->x_min = ((li->x_max - li->x_min) + xof_scale);
if (li->char_nr > 1) {
li->x_min /= (float)(li->char_nr - 1);
}
}
for (i = 0; i <= slen; i++) {
for (j = i; (!ELEM(mem[j], '\0', '\n')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) {
/* do nothing */
}
// if ((mem[j] != '\n') && (mem[j])) {
ct->xof += ct->charnr * lineinfo[ct->linenr].x_min;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
// }
2002-10-12 11:37:38 +00:00
ct++;
}
}
2016-06-21 12:44:49 +10:00
else if ((cu->spacemode == CU_ALIGN_X_JUSTIFY) && use_textbox) {
float curofs = 0.0f;
for (i = 0; i <= slen; i++) {
for (j = i;
(mem[j]) && (mem[j] != '\n') && (chartransdata[j].dobreak == 0) && (j < slen);
j++)
{
/* pass */
}
if ((mem[j] != '\n') &&
((chartransdata[j].dobreak != 0)))
{
if (mem[i] == ' ') {
struct TempLineInfo *li;
li = &lineinfo[ct->linenr];
curofs += ((li->x_max - li->x_min) + xof_scale) / (float)li->wspace_nr;
}
ct->xof += curofs;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
}
if (mem[i] == '\n' || chartransdata[i].dobreak) curofs = 0;
More text object fancyness, and fixes: - "Flush" is now split into two seperate Alignment modes "Flush" and "Justify": - Justify does exactly the same as a normal word processor's justify function does, and in addition, it uses *whitespace* instead of *character spacing* (kerning) to fill lines. Much more readable. - Flush is pretty much the old Blender "Flush" mode - and as such it uses character spacing to fill lines. Just as Justify, this only works with at least one textframe. - Underlining for text objects. Not a lot to explain. New button "U" in the editbuttons, and CTRL-U as hotkey toggle underlining for newly entered characters or for the selection, just like CTRL-B/CTRL-I do for bold/italic. Underline height (thickness) and Underline position (vertical) can be set in the editbuttons. Implemented as CU_POLY polygon curves. - The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes) have been fixed to only affect *one* attribute at a time. Formerly, hitting CTRL-B when no other style was active, on a text portion with italics text, for example, would kill the italics and just apply bold. Now, these attributes always add or substract only, but do not replace the style. - In the past, there were bugs with material indices uninitialized, and thus crashes in the renderer with illegal material indices. Even though I assume they have been fixed, I've put in a check that checks (hah) if the material index of a character is illegal (bigger than ob->totcol), and then sets it to zero, and spits out a warning on stderr. If you see such warnings, please report and link to the .blend. - Bugfix: All alignment modes only worked if there were at least *two* lines of text in the text object. Fixed There's now a regression test file for text objects, please add to the corresponding repository: http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
2005-08-29 12:46:07 +00:00
ct++;
}
2002-10-12 11:37:38 +00:00
}
}
/* top-baseline is default, in this case, do nothing */
if (cu->align_y != CU_ALIGN_Y_TOP_BASELINE) {
if (tb_scale.h != 0.0f) {
/* top and top-baseline are the same when text-boxes are used */
if (cu->align_y != CU_ALIGN_Y_TOP && i_textbox < slen) {
/* all previous textboxes are 'full', only align the last used text-box */
float yoff;
int lines;
struct CharTrans *ct_last, *ct_textbox;
ct_last = chartransdata + slen - 1;
ct_textbox = chartransdata + i_textbox;
lines = ct_last->linenr - ct_textbox->linenr + 1;
if (mem[slen - 1] == '\n') {
lines++;
}
if (cu->align_y == CU_ALIGN_Y_BOTTOM) {
yoff = (lines * linedist) - tb_scale.h;
}
else if (cu->align_y == CU_ALIGN_Y_CENTER) {
yoff = 0.5f * ((lines * linedist) - tb_scale.h);
}
ct = ct_textbox;
for (i = i_textbox - 1; i < slen; i++) {
ct->yof += yoff;
ct++;
}
}
}
else {
/* non text-box case handled separately */
ct = chartransdata;
float yoff;
if (cu->align_y == CU_ALIGN_Y_TOP) {
yoff = -linedist;
}
else if (cu->align_y == CU_ALIGN_Y_BOTTOM) {
yoff = (lnr - 1.0f) * linedist;
}
else if (cu->align_y == CU_ALIGN_Y_CENTER) {
yoff = (lnr - 2.0f) * linedist * 0.5f;
}
for (i = 0; i <= slen; i++) {
ct->yof += yoff;
ct++;
}
}
}
MEM_freeN(lineinfo);
2002-10-12 11:37:38 +00:00
/* TEXT ON CURVE */
/* Note: Only OB_CURVE objects could have a path */
if (cu->textoncurve && cu->textoncurve->type == OB_CURVE) {
BLI_assert(cu->textoncurve->curve_cache != NULL);
if (cu->textoncurve->curve_cache->path) {
float distfac, imat[4][4], imat3[3][3], cmat[3][3];
float minx, maxx, miny, maxy;
float timeofs, sizefac;
invert_m4_m4(imat, ob->obmat);
copy_m3_m4(imat3, imat);
2002-10-12 11:37:38 +00:00
copy_m3_m4(cmat, cu->textoncurve->obmat);
mul_m3_m3m3(cmat, cmat, imat3);
sizefac = normalize_v3(cmat[0]) / cu->fsize;
2002-10-12 11:37:38 +00:00
minx = miny = 1.0e20f;
maxx = maxy = -1.0e20f;
ct = chartransdata;
for (i = 0; i <= slen; i++, ct++) {
if (minx > ct->xof) minx = ct->xof;
if (maxx < ct->xof) maxx = ct->xof;
if (miny > ct->yof) miny = ct->yof;
if (maxy < ct->yof) maxy = ct->yof;
2002-10-12 11:37:38 +00:00
}
/* we put the x-coordinaat exact at the curve, the y is rotated */
2002-10-12 11:37:38 +00:00
/* length correction */
distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx);
timeofs = 0.0f;
2002-10-12 11:37:38 +00:00
if (distfac > 1.0f) {
/* path longer than text: spacemode involves */
distfac = 1.0f / distfac;
2002-10-12 11:37:38 +00:00
2016-06-21 12:44:49 +10:00
if (cu->spacemode == CU_ALIGN_X_RIGHT) {
timeofs = 1.0f - distfac;
2002-10-12 11:37:38 +00:00
}
2016-06-21 12:44:49 +10:00
else if (cu->spacemode == CU_ALIGN_X_MIDDLE) {
timeofs = (1.0f - distfac) / 2.0f;
2002-10-12 11:37:38 +00:00
}
2016-06-21 12:44:49 +10:00
else if (cu->spacemode == CU_ALIGN_X_FLUSH) {
2012-08-04 19:34:38 +00:00
distfac = 1.0f;
}
2002-10-12 11:37:38 +00:00
}
2012-08-04 19:34:38 +00:00
else {
distfac = 1.0;
}
distfac /= (maxx - minx);
2002-10-12 11:37:38 +00:00
timeofs += distfac * cu->xof; /* not cyclic */
2002-10-12 11:37:38 +00:00
ct = chartransdata;
for (i = 0; i < slen; i++, ct++) {
float ctime, dtime, vec[4], tvec[4], rotvec[3];
float si, co;
2002-10-12 11:37:38 +00:00
/* rotate around center character */
info = &custrinfo[i];
ascii = mem[i];
if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
ascii = towupper(ascii);
}
che = find_vfont_char(vfd, ascii);
twidth = char_width(cu, che, info);
dtime = distfac * 0.5f * twidth;
ctime = timeofs + distfac * (ct->xof - minx);
CLAMP(ctime, 0.0f, 1.0f);
/* calc the right loc AND the right rot separately */
/* vec, tvec need 4 items */
where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
where_on_path(cu->textoncurve, ctime + dtime, tvec, rotvec, NULL, NULL, NULL);
2002-10-12 11:37:38 +00:00
mul_v3_fl(vec, sizefac);
2002-10-12 11:37:38 +00:00
2012-08-04 19:34:38 +00:00
ct->rot = (float)M_PI - atan2f(rotvec[1], rotvec[0]);
2002-10-12 11:37:38 +00:00
2012-08-04 19:34:38 +00:00
si = sinf(ct->rot);
co = cosf(ct->rot);
2002-10-12 11:37:38 +00:00
yof = ct->yof;
2002-10-12 11:37:38 +00:00
ct->xof = vec[0] + si * yof;
ct->yof = vec[1] + co * yof;
if (selboxes && (i >= selstart) && (i <= selend)) {
EditFontSelBox *sb;
sb = &selboxes[i - selstart];
sb->rot = -ct->rot;
}
2002-10-12 11:37:38 +00:00
}
/* null character is always zero width, no need to iterate over it */
chartransdata[slen] = chartransdata[slen - 1];
2002-10-12 11:37:38 +00:00
}
}
if (selboxes) {
ct = chartransdata;
for (i = 0; i <= selend; i++, ct++) {
if (i >= selstart) {
selboxes[i - selstart].x = ct->xof * cu->fsize;
selboxes[i - selstart].y = ct->yof * cu->fsize;
}
}
}
2002-10-12 11:37:38 +00:00
if (mode == FO_CURSUP || mode == FO_CURSDOWN || mode == FO_PAGEUP || mode == FO_PAGEDOWN) {
ct = &chartransdata[ef->pos];
2012-10-07 09:48:59 +00:00
if ((mode == FO_CURSUP || mode == FO_PAGEUP) && ct->linenr == 0) {
/* pass */
}
else if ((mode == FO_CURSDOWN || mode == FO_PAGEDOWN) && ct->linenr == lnr) {
/* pass */
}
2002-10-12 11:37:38 +00:00
else {
switch (mode) {
case FO_CURSUP: lnr = ct->linenr - 1; break;
case FO_CURSDOWN: lnr = ct->linenr + 1; break;
case FO_PAGEUP: lnr = ct->linenr - 10; break;
case FO_PAGEDOWN: lnr = ct->linenr + 10; break;
}
cnr = ct->charnr;
/* seek for char with lnr en cnr */
ef->pos = 0;
ct = chartransdata;
for (i = 0; i < slen; i++) {
if (ct->linenr == lnr) {
if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) {
break;
}
}
else if (ct->linenr > lnr) {
break;
2002-10-12 11:37:38 +00:00
}
ef->pos++;
2002-10-12 11:37:38 +00:00
ct++;
}
}
}
/* cursor first */
if (ef) {
float si, co;
ct = &chartransdata[ef->pos];
si = sinf(ct->rot);
co = cosf(ct->rot);
f = ef->textcurs[0];
2002-10-12 11:37:38 +00:00
f[0] = cu->fsize * (-0.1f * co + ct->xof);
2012-08-04 19:34:38 +00:00
f[1] = cu->fsize * ( 0.1f * si + ct->yof);
2002-10-12 11:37:38 +00:00
2012-08-04 19:34:38 +00:00
f[2] = cu->fsize * ( 0.1f * co + ct->xof);
f[3] = cu->fsize * (-0.1f * si + ct->yof);
2002-10-12 11:37:38 +00:00
2012-08-04 19:34:38 +00:00
f[4] = cu->fsize * ( 0.1f * co + 0.8f * si + ct->xof);
f[5] = cu->fsize * (-0.1f * si + 0.8f * co + ct->yof);
2002-10-12 11:37:38 +00:00
f[6] = cu->fsize * (-0.1f * co + 0.8f * si + ct->xof);
2012-08-04 19:34:38 +00:00
f[7] = cu->fsize * ( 0.1f * si + 0.8f * co + ct->yof);
2002-10-12 11:37:38 +00:00
}
if (mode == FO_SELCHANGE) {
MEM_freeN(chartransdata);
chartransdata = NULL;
goto finally;
}
if (mode == FO_EDIT) {
/* make nurbdata */
BKE_nurbList_free(r_nubase);
2002-10-12 11:37:38 +00:00
ct = chartransdata;
for (i = 0; i < slen; i++) {
unsigned int cha = (unsigned int) mem[i];
info = &(custrinfo[i]);
if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
cha = towupper(cha);
}
if (info->mat_nr > (ob->totcol)) {
/* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
info->mat_nr = 0;
}
/* We do not want to see any character for \n or \r */
if (cha != '\n')
buildchar(bmain, cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i);
if ((info->flag & CU_CHINFO_UNDERLINE) && (cha != '\n')) {
float ulwidth, uloverlap = 0.0f;
rctf rect;
if ((i < (slen - 1)) && (mem[i + 1] != '\n') &&
((mem[i + 1] != ' ') || (custrinfo[i + 1].flag & CU_CHINFO_UNDERLINE)) &&
((custrinfo[i + 1].flag & CU_CHINFO_WRAP) == 0))
{
uloverlap = xtrax + 0.1f;
}
/* Find the character, the characters has to be in the memory already
* since character checking has been done earlier already. */
che = find_vfont_char(vfd, cha);
twidth = char_width(cu, che, info);
ulwidth = (twidth * (1.0f + (info->kern / 40.0f))) + uloverlap;
rect.xmin = ct->xof;
rect.xmax = rect.xmin + ulwidth;
rect.ymin = ct->yof;
rect.ymax = rect.ymin - cu->ulheight;
build_underline(cu, r_nubase,
&rect, cu->ulpos - 0.05f,
ct->rot, i, info->mat_nr);
}
ct++;
}
}
2002-10-12 11:37:38 +00:00
ok = true;
finally:
2002-10-12 11:37:38 +00:00
{
if (r_text) {
*r_text = mem;
*r_text_len = slen;
*r_text_free = (ef == NULL);
}
else {
if (ef == NULL) {
MEM_freeN((void *)mem);
}
}
}
if (chartransdata) {
if (ok && r_chartransdata) {
*r_chartransdata = chartransdata;
}
else {
MEM_freeN(chartransdata);
}
}
return ok;
#undef MARGIN_X_MIN
#undef MARGIN_Y_MIN
2002-10-12 11:37:38 +00:00
}
bool BKE_vfont_to_curve_nubase(Main *bmain, Object *ob, int mode, ListBase *r_nubase)
{
BLI_assert(ob->type == OB_FONT);
return BKE_vfont_to_curve_ex(bmain, ob, mode, r_nubase,
NULL, NULL, NULL, NULL);
}
bool BKE_vfont_to_curve(Main *bmain, Object *ob, int mode)
{
Curve *cu = ob->data;
return BKE_vfont_to_curve_ex(bmain, ob, mode, &cu->nurb, NULL, NULL, NULL, NULL);
}
/* -------------------------------------------------------------------- */
/** \name VFont Clipboard
* \{ */
static struct {
wchar_t *text_buffer;
CharInfo *info_buffer;
size_t len_wchar;
size_t len_utf8;
} g_vfont_clipboard = {NULL};
void BKE_vfont_clipboard_free(void)
{
MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
g_vfont_clipboard.len_wchar = 0;
g_vfont_clipboard.len_utf8 = 0;
}
void BKE_vfont_clipboard_set(const wchar_t *text_buf, const CharInfo *info_buf, const size_t len)
{
wchar_t *text;
CharInfo *info;
/* clean previous buffers*/
BKE_vfont_clipboard_free();
text = MEM_mallocN((len + 1) * sizeof(wchar_t), __func__);
if (text == NULL) {
return;
}
info = MEM_mallocN(len * sizeof(CharInfo), __func__);
if (info == NULL) {
MEM_freeN(text);
return;
}
memcpy(text, text_buf, len * sizeof(wchar_t));
text[len] = '\0';
memcpy(info, info_buf, len * sizeof(CharInfo));
/* store new buffers */
g_vfont_clipboard.text_buffer = text;
g_vfont_clipboard.info_buffer = info;
g_vfont_clipboard.len_utf8 = BLI_wstrlen_utf8(text);
g_vfont_clipboard.len_wchar = len;
}
void BKE_vfont_clipboard_get(
wchar_t **r_text_buf, CharInfo **r_info_buf,
size_t *r_len_utf8, size_t *r_len_wchar)
{
if (r_text_buf) {
*r_text_buf = g_vfont_clipboard.text_buffer;
}
if (r_info_buf) {
*r_info_buf = g_vfont_clipboard.info_buffer;
}
if (r_len_wchar) {
*r_len_wchar = g_vfont_clipboard.len_wchar;
}
if (r_len_utf8) {
*r_len_utf8 = g_vfont_clipboard.len_utf8;
}
}
/** \} */