コード例 #1
0
ファイル: editcurve_undo.c プロジェクト: dfelinto/blender
static void undocurve_free_data(UndoCurve *uc)
{
  BKE_nurbList_free(&uc->nubase);

  BKE_curve_editNurb_keyIndex_free(&uc->undoIndex);

  free_fcurves(&uc->fcurves);
  free_fcurves(&uc->drivers);
}
コード例 #2
0
static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys)
{
	DerivedMesh *dm;
	bool dm_needsFree;

	if (ob->type == OB_MESH || ob->derivedFinal) {
		dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
		dm_needsFree = false;
	}
	else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
		dm = CDDM_from_curve(ob);
		dm_needsFree = true;
	}
	else {
		dm = NULL;
	}

	if (dm) {
		ListBase nurbslist = {NULL, NULL};
		float projmat[4][4];

		BKE_mesh_to_curve_nurblist(dm, &nurbslist, 0);  /* wire */
		BKE_mesh_to_curve_nurblist(dm, &nurbslist, 1);  /* boundary */

		ED_view3d_ob_project_mat_get(ar->regiondata, ob, projmat);

		if (nurbslist.first) {
			Nurb *nu;
			for (nu = nurbslist.first; nu; nu = nu->next) {
				if (nu->bp) {
					int a;
					BPoint *bp;
					bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
					float (*mval)[2] = MEM_mallocN(sizeof(*mval) * (nu->pntsu + is_cyclic), __func__);

					for (bp = nu->bp, a = 0; a < nu->pntsu; a++, bp++) {
						ED_view3d_project_float_v2_m4(ar, bp->vec, mval[a], projmat);
					}
					if (is_cyclic) {
						copy_v2_v2(mval[a], mval[0]);
					}

					BLI_linklist_prepend(&polys, mval);
				}
			}
		}

		BKE_nurbList_free(&nurbslist);

		if (dm_needsFree) {
			dm->release(dm);
		}
	}


	return polys;
}
コード例 #3
0
ファイル: editcurve_undo.c プロジェクト: dfelinto/blender
static void undocurve_to_editcurve(Main *bmain, UndoCurve *ucu, Curve *cu, short *r_shapenr)
{
  ListBase *undobase = &ucu->nubase;
  ListBase *editbase = BKE_curve_editNurbs_get(cu);
  Nurb *nu, *newnu;
  EditNurb *editnurb = cu->editnurb;
  AnimData *ad = BKE_animdata_from_id(&cu->id);

  BKE_nurbList_free(editbase);

  if (ucu->undoIndex) {
    BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
    editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex);
  }

  if (ad) {
    if (ad->action) {
      free_fcurves(&ad->action->curves);
      copy_fcurves(&ad->action->curves, &ucu->fcurves);
    }

    free_fcurves(&ad->drivers);
    copy_fcurves(&ad->drivers, &ucu->drivers);
  }

  /* copy  */
  for (nu = undobase->first; nu; nu = nu->next) {
    newnu = BKE_nurb_duplicate(nu);

    if (editnurb->keyindex) {
      ED_curve_keyindex_update_nurb(editnurb, nu, newnu);
    }

    BLI_addtail(editbase, newnu);
  }

  cu->actvert = ucu->actvert;
  cu->actnu = ucu->actnu;
  cu->flag = ucu->flag;
  *r_shapenr = ucu->obedit.shapenr;
  ED_curve_updateAnimPaths(bmain, cu);
}
コード例 #4
0
ファイル: displist.c プロジェクト: mgschwan/blensor
void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
                            DerivedMesh **r_dm_final,
                            const bool for_render, const bool for_orco, const bool use_render_resolution)
{
	ListBase nubase = {NULL, NULL};
	Nurb *nu;
	Curve *cu = ob->data;
	DispList *dl;
	float *data;
	int len;

	if (!for_render && cu->editnurb) {
		BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu));
	}
	else {
		BKE_nurbList_duplicate(&nubase, &cu->nurb);
	}

	if (!for_orco)
		curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution);

	for (nu = nubase.first; nu; nu = nu->next) {
		if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) {
			int resolu = nu->resolu, resolv = nu->resolv;

			if (use_render_resolution) {
				if (cu->resolu_ren)
					resolu = cu->resolu_ren;
				if (cu->resolv_ren)
					resolv = cu->resolv_ren;
			}

			if (nu->pntsv == 1) {
				len = SEGMENTSU(nu) * resolu;

				dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
				dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");

				BLI_addtail(dispbase, dl);
				dl->parts = 1;
				dl->nr = len;
				dl->col = nu->mat_nr;
				dl->charidx = nu->charidx;

				/* dl->rt will be used as flag for render face and */
				/* CU_2D conflicts with R_NOPUNOFLIP */
				dl->rt = nu->flag & ~CU_2D;

				data = dl->verts;
				if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY;
				else dl->type = DL_SEGM;

				BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float));
			}
			else {
				len = (nu->pntsu * resolu) * (nu->pntsv * resolv);

				dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
				dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
				BLI_addtail(dispbase, dl);

				dl->col = nu->mat_nr;
				dl->charidx = nu->charidx;

				/* dl->rt will be used as flag for render face and */
				/* CU_2D conflicts with R_NOPUNOFLIP */
				dl->rt = nu->flag & ~CU_2D;

				data = dl->verts;
				dl->type = DL_SURF;

				dl->parts = (nu->pntsu * resolu);  /* in reverse, because makeNurbfaces works that way */
				dl->nr = (nu->pntsv * resolv);
				if (nu->flagv & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_U;  /* reverse too! */
				if (nu->flagu & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_V;

				BKE_nurb_makeFaces(nu, data, 0, resolu, resolv);

				/* gl array drawing: using indices */
				displist_surf_indices(dl);
			}
		}
	}

	if (!for_orco) {
		BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
		curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final,
		                          for_render, use_render_resolution);
	}

	BKE_nurbList_free(&nubase);
}
コード例 #5
0
ファイル: font.c プロジェクト: JasonWilkins/blender-wayland
struct CharTrans *BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode)
{
	VFont *vfont, *oldvfont;
	VFontData *vfd = NULL;
	Curve *cu;
	CharInfo *info = NULL, *custrinfo;
	TextBox *tb;
	VChar *che;
	struct CharTrans *chartransdata = NULL, *ct;
	float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
	float twidth, maxlen = 0;
	int i, slen, j;
	int curbox;
	int selstart, selend;
	int utf8len;
	short cnr = 0, lnr = 0, wsnr = 0;
	wchar_t *mem, *tmp, ascii;

	/* remark: do calculations including the trailing '\0' of a string
	 * because the cursor can be at that location */

	if (ob->type != OB_FONT) return NULL;

	/* Set font data */
	cu = (Curve *) ob->data;
	vfont = cu->vfont;

	if (cu->str == NULL) return NULL;
	if (vfont == NULL) return NULL;

	/* Create unicode string */
	utf8len = BLI_strlen_utf8(cu->str);
	mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");

	BLI_strncpy_wchar_from_utf8(mem, cu->str, utf8len + 1);

	/* Count the wchar_t string length */
	slen = wcslen(mem);

	if (cu->ulheight == 0.0f)
		cu->ulheight = 0.05f;
	
	if (cu->strinfo == NULL) /* old file */
		cu->strinfo = MEM_callocN((slen + 4) * sizeof(CharInfo), "strinfo compat");
	
	custrinfo = cu->strinfo;
	if (cu->editfont)
		custrinfo = cu->editfont->textbufinfo;
	
	if (cu->tb == NULL)
		cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "TextBox compat");

	vfd = vfont_get_data(bmain, vfont);

	/* The VFont Data can not be found */
	if (!vfd) {
		if (mem)
			MEM_freeN(mem);
		return NULL;
	}

	/* calc offset and rotation of each char */
	ct = chartransdata =
	         (struct CharTrans *)MEM_callocN((slen + 1) * sizeof(struct CharTrans), "buildtext");

	/* We assume the worst case: 1 character per line (is freed at end anyway) */

	linedata  = MEM_mallocN(sizeof(float) * (slen * 2 + 1), "buildtext2");
	linedata2 = MEM_mallocN(sizeof(float) * (slen * 2 + 1), "buildtext3");
	linedata3 = MEM_callocN(sizeof(float) * (slen * 2 + 1), "buildtext4");
	linedata4 = MEM_callocN(sizeof(float) * (slen * 2 + 1), "buildtext5");
	
	linedist = cu->linedist;
	
	xof = cu->xof + (cu->tb[0].x / cu->fsize);
	yof = cu->yof + (cu->tb[0].y / cu->fsize);

	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);

	if (cu->selboxes) MEM_freeN(cu->selboxes);
	cu->selboxes = NULL;
	if (BKE_vfont_select_get(ob, &selstart, &selend))
		cu->selboxes = MEM_callocN((selend - selstart + 1) * sizeof(SelBox), "font selboxes");

	tb = &(cu->tb[0]);
	curbox = 0;
	for (i = 0; i <= slen; i++) {
makebreak:
		/* Characters in the list */
		info = &(custrinfo[i]);
		ascii = mem[i];
		if (info->flag & CU_CHINFO_SMALLCAPS) {
			ascii = towupper(ascii);
			if (mem[i] != ascii) {
				mem[i] = ascii;
				info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
			}
		}

		vfont = which_vfont(cu, info);
		
		if (vfont == NULL) break;

		che = find_vfont_char(vfd, ascii);

		/*
		 * 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_vfontchar_from_freetypefont(vfont, ascii);
		}

		/* Try getting the character again from the list */
		che = find_vfont_char(vfd, ascii);

		/* No VFont found */
		if (vfont == NULL) {
			if (mem)
				MEM_freeN(mem);
			MEM_freeN(chartransdata);
			return NULL;
		}

		if (vfont != oldvfont) {
			vfd = vfont_get_data(bmain, vfont);
			oldvfont = vfont;
		}

		/* VFont Data for VFont couldn't be found */
		if (!vfd) {
			if (mem)
				MEM_freeN(mem);
			MEM_freeN(chartransdata);
			return NULL;
		}

		twidth = char_width(cu, che, info);

		/* Calculate positions */
		if ((tb->w != 0.0f) &&
		    (ct->dobreak == 0) &&
		    (((xof - (tb->x / cu->fsize) + twidth) * cu->fsize) > tb->w + cu->xof * cu->fsize))
		{
			//		fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
			for (j = i; j && (mem[j] != '\n') && (mem[j] != '\r') && (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;
				}
			}
		}

		if (ascii == '\n' || ascii == '\r' || ascii == 0 || ct->dobreak) {
			ct->xof = xof;
			ct->yof = yof;
			ct->linenr = lnr;
			ct->charnr = cnr;

			yof -= linedist;

			maxlen = max_ff(maxlen, (xof - tb->x / cu->fsize));
			linedata[lnr] = xof - tb->x / cu->fsize;
			linedata2[lnr] = cnr;
			linedata3[lnr] = tb->w / cu->fsize;
			linedata4[lnr] = wsnr;
			
			if ((tb->h != 0.0f) &&
			    ((-(yof - (tb->y / cu->fsize))) > ((tb->h / cu->fsize) - (linedist * cu->fsize)) - cu->yof) &&
			    (cu->totbox > (curbox + 1)) )
			{
				maxlen = 0;
				tb++;
				curbox++;
				yof = cu->yof + tb->y / cu->fsize;
			}

			/* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
#if 0
			if (ascii == '\n' || ascii == '\r')
				xof = cu->xof;
			else
				xof = cu->xof + (tb->x / cu->fsize);
#else
			xof = cu->xof + (tb->x / cu->fsize);
#endif
			lnr++;
			cnr = 0;
			wsnr = 0;
		}
		else if (ascii == 9) {    /* TAB */
			float tabfac;
			
			ct->xof = xof;
			ct->yof = yof;
			ct->linenr = lnr;
			ct->charnr = cnr++;

			tabfac = (xof - cu->xof + 0.01f);
			tabfac = 2.0f * ceilf(tabfac / 2.0f);
			xof = cu->xof + tabfac;
		}
		else {
			SelBox *sb = NULL;
			float wsfac;

			ct->xof = xof;
			ct->yof = yof;
			ct->linenr = lnr;
			ct->charnr = cnr++;

			if (cu->selboxes && (i >= selstart) && (i <= selend)) {
				sb = &(cu->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) {
				wsfac = cu->wordspace; 
				wsnr++;
			}
			else {
				wsfac = 1.0f;
			}
			
			/* Set the width of the character */
			twidth = char_width(cu, che, info);

			xof += (twidth * wsfac * (1.0f + (info->kern / 40.0f)) ) + xtrax;
			
			if (sb) {
				sb->w = (xof * cu->fsize) - sb->w;
			}
		}
		ct++;
	}
	
	cu->lines = 1;
	ct = chartransdata;
	tmp = mem;
	for (i = 0; i <= slen; i++, tmp++, ct++) {
		ascii = *tmp;
		if (ascii == '\n' || ascii == '\r' || ct->dobreak) cu->lines++;
	}

	/* linedata is now: width of line
	 * linedata2 is now: number of characters
	 * linedata3 is now: maxlen of that line
	 * linedata4 is now: number of whitespaces of line */

	if (cu->spacemode != CU_LEFT) {
		ct = chartransdata;

		if (cu->spacemode == CU_RIGHT) {
			for (i = 0; i < lnr; i++) linedata[i] = linedata3[i] - linedata[i];
			for (i = 0; i <= slen; i++) {
				ct->xof += linedata[ct->linenr];
				ct++;
			}
		}
		else if (cu->spacemode == CU_MIDDLE) {
			for (i = 0; i < lnr; i++) linedata[i] = (linedata3[i] - linedata[i]) / 2;
			for (i = 0; i <= slen; i++) {
				ct->xof += linedata[ct->linenr];
				ct++;
			}
		}
		else if ((cu->spacemode == CU_FLUSH) && (cu->tb[0].w != 0.0f)) {
			for (i = 0; i < lnr; i++)
				if (linedata2[i] > 1)
					linedata[i] = (linedata3[i] - linedata[i]) / (linedata2[i] - 1);
			for (i = 0; i <= slen; i++) {
				for (j = i; (!ELEM3(mem[j], '\0', '\n', '\r')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) {
					/* do nothing */
				}

//				if ((mem[j] != '\r') && (mem[j] != '\n') && (mem[j])) {
				ct->xof += ct->charnr * linedata[ct->linenr];
//				}
				ct++;
			}
		}
		else if ((cu->spacemode == CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) {
			float curofs = 0.0f;
			for (i = 0; i <= slen; i++) {
				for (j = i; (mem[j]) && (mem[j] != '\n') &&
				     (mem[j] != '\r') && (chartransdata[j].dobreak == 0) && (j < slen);
				     j++)
				{
					/* pass */
				}

				if ((mem[j] != '\r') && (mem[j] != '\n') &&
				    ((chartransdata[j].dobreak != 0)))
				{
					if (mem[i] == ' ') curofs += (linedata3[ct->linenr] - linedata[ct->linenr]) / linedata4[ct->linenr];
					ct->xof += curofs;
				}
				if (mem[i] == '\n' || mem[i] == '\r' || chartransdata[i].dobreak) curofs = 0;
				ct++;
			}
		}
	}
	
	/* TEXT ON CURVE */
	/* Note: Only OB_CURVE objects could have a path  */
	if (cu->textoncurve && cu->textoncurve->type == OB_CURVE) {
		Curve *cucu = cu->textoncurve->data;
		int oldflag = cucu->flag;
		
		cucu->flag |= (CU_PATH + CU_FOLLOW);
		
		if (cucu->path == NULL) BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
		if (cucu->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);

			copy_m3_m4(cmat, cu->textoncurve->obmat);
			mul_m3_m3m3(cmat, cmat, imat3);
			sizefac = normalize_v3(cmat[0]) / cu->fsize;
			
			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;
			}
			
			/* we put the x-coordinaat exact at the curve, the y is rotated */
			
			/* length correction */
			distfac = sizefac * cucu->path->totdist / (maxx - minx);
			timeofs = 0.0f;
			
			if (distfac > 1.0f) {
				/* path longer than text: spacemode involves */
				distfac = 1.0f / distfac;
				
				if (cu->spacemode == CU_RIGHT) {
					timeofs = 1.0f - distfac;
				}
				else if (cu->spacemode == CU_MIDDLE) {
					timeofs = (1.0f - distfac) / 2.0f;
				}
				else if (cu->spacemode == CU_FLUSH) {
					distfac = 1.0f;
				}
			}
			else {
				distfac = 1.0;
			}

			distfac /= (maxx - minx);
			
			timeofs += distfac * cu->xof;  /* not cyclic */
			
			ct = chartransdata;
			for (i = 0; i <= slen; i++, ct++) {
				float ctime, dtime, vec[4], tvec[4], rotvec[3];
				float si, co;
				
				/* rotate around center character */
				ascii = mem[i];

				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);
				
				mul_v3_fl(vec, sizefac);
				
				ct->rot = (float)M_PI - atan2f(rotvec[1], rotvec[0]);

				si = sinf(ct->rot);
				co = cosf(ct->rot);

				yof = ct->yof;
				
				ct->xof = vec[0] + si * yof;
				ct->yof = vec[1] + co * yof;
				
			}
			cucu->flag = oldflag;
		}
	}

	if (cu->selboxes) {
		ct = chartransdata;
		for (i = 0; i <= selend; i++, ct++) {
			if (i >= selstart) {
				cu->selboxes[i - selstart].x = ct->xof * cu->fsize;
				cu->selboxes[i - selstart].y = ct->yof * cu->fsize;
			}
		}
	}

	if (mode == FO_CURSUP || mode == FO_CURSDOWN || mode == FO_PAGEUP || mode == FO_PAGEDOWN) {
		/* 2: curs up
		 * 3: curs down */
		ct = chartransdata + cu->pos;
		
		if ((mode == FO_CURSUP || mode == FO_PAGEUP) && ct->linenr == 0) {
			/* pass */
		}
		else if ((mode == FO_CURSDOWN || mode == FO_PAGEDOWN) && ct->linenr == lnr) {
			/* pass */
		}
		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 */
			cu->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;
				}
				cu->pos++;
				ct++;
			}
		}
	}
	
	/* cursor first */
	if (cu->editfont) {
		float si, co;
		
		ct = chartransdata + cu->pos;
		si = sinf(ct->rot);
		co = cosf(ct->rot);

		f = cu->editfont->textcurs[0];
		
		f[0] = cu->fsize * (-0.1f * co + ct->xof);
		f[1] = cu->fsize * ( 0.1f * si + ct->yof);
		
		f[2] = cu->fsize * ( 0.1f * co + ct->xof);
		f[3] = cu->fsize * (-0.1f * si + ct->yof);
		
		f[4] = cu->fsize * ( 0.1f * co + 0.8f * si + ct->xof);
		f[5] = cu->fsize * (-0.1f * si + 0.8f * co + ct->yof);
		
		f[6] = cu->fsize * (-0.1f * co + 0.8f * si + ct->xof);
		f[7] = cu->fsize * ( 0.1f * si + 0.8f * co + ct->yof);
		
	}

	MEM_freeN(linedata);
	MEM_freeN(linedata2);
	MEM_freeN(linedata3);
	MEM_freeN(linedata4);

	if (mode == FO_SELCHANGE) {
		MEM_freeN(chartransdata);
		MEM_freeN(mem);
		return NULL;
	}

	if (mode == FO_EDIT) {
		/* make nurbdata */
		BKE_nurbList_free(&cu->nurb);
		
		ct = chartransdata;
		if (cu->sepchar == 0) {
			for (i = 0; i < slen; i++) {
				unsigned long cha = (uintptr_t) mem[i];
				info = &(custrinfo[i]);
				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' && cha != '\r')
					buildchar(bmain, cu, cha, info, ct->xof, ct->yof, ct->rot, i);
				
				if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
					float ulwidth, uloverlap = 0.0f;
					
					if ((i < (slen - 1)) && (mem[i + 1] != '\n') && (mem[i + 1] != '\r') &&
					    ((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 = cu->fsize * ((twidth * (1.0f + (info->kern / 40.0f))) + uloverlap);
					build_underline(cu, ct->xof * cu->fsize, ct->yof * cu->fsize + (cu->ulpos - 0.05f) * cu->fsize,
					                ct->xof * cu->fsize + ulwidth,
					                ct->yof * cu->fsize + (cu->ulpos - 0.05f) * cu->fsize - cu->ulheight * cu->fsize,
					                i, info->mat_nr);
				}
				ct++;
			}
		}
		else {
			int outta = 0;
			for (i = 0; (i < slen) && (outta == 0); i++) {
				ascii = mem[i];
				info = &(custrinfo[i]);
				if (cu->sepchar == (i + 1)) {
					float vecyo[3];

					vecyo[0] = ct->xof;
					vecyo[1] = ct->yof;
					vecyo[2] = 0.0f;

					mem[0] = ascii;
					mem[1] = 0;
					custrinfo[0] = *info;
					cu->pos = 1;
					cu->len = 1;
					mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
					outta = 1;
					cu->sepchar = 0;
				}
				ct++;
			}
		}
	}

	if (mode == FO_DUPLI) {
		MEM_freeN(mem);
		return chartransdata;
	}

	if (mem)
		MEM_freeN(mem);

	MEM_freeN(chartransdata);
	return NULL;
}