Refactor: Simplify vfontdata_freetype.c #109224
|
@ -36,232 +36,188 @@
|
|||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_vfont_types.h"
|
||||
|
||||
static VChar *freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
|
||||
static void freetype_outline_to_curves(FT_Outline ftoutline, ListBase *nurbsbase, const float scale)
|
||||
Harley marked this conversation as resolved
Outdated
|
||||
{
|
||||
const float scale = vfd->scale;
|
||||
const float eps = 0.0001f;
|
||||
const float eps_sq = eps * eps;
|
||||
/* Blender */
|
||||
Nurb *nu;
|
||||
VChar *che;
|
||||
BezTriple *bezt;
|
||||
|
||||
/* Freetype2 */
|
||||
FT_GlyphSlot glyph;
|
||||
FT_UInt glyph_index;
|
||||
FT_Outline ftoutline;
|
||||
float dx, dy;
|
||||
int j, k, l, l_first = 0;
|
||||
|
||||
/*
|
||||
* Generate the character 3D data
|
||||
*
|
||||
* Get the FT Glyph index and load the Glyph */
|
||||
glyph_index = FT_Get_Char_Index(face, charcode);
|
||||
FT_Error err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
|
||||
/* initialize as -1 to add 1 on first loop each time */
|
||||
int contour_prev;
|
||||
|
||||
/* If loading succeeded, convert the FT glyph to the internal format */
|
||||
if (!err) {
|
||||
/* initialize as -1 to add 1 on first loop each time */
|
||||
int contour_prev;
|
||||
int *onpoints;
|
||||
/* Start converting the FT data */
|
||||
int *onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints");
|
||||
|
||||
/* First we create entry for the new character to the character list */
|
||||
che = (VChar *)MEM_callocN(sizeof(VChar), "objfnt_char");
|
||||
/* Get number of on-curve points for bezier-triples (including conic virtual on-points). */
|
||||
for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
|
||||
const int n = ftoutline.contours[j] - contour_prev;
|
||||
contour_prev = ftoutline.contours[j];
|
||||
|
||||
/* Take some data for modifying purposes */
|
||||
glyph = face->glyph;
|
||||
ftoutline = glyph->outline;
|
||||
for (k = 0; k < n; k++) {
|
||||
l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
|
||||
if (k == 0) {
|
||||
l_first = l;
|
||||
}
|
||||
|
||||
/* Set the width and character code */
|
||||
che->index = charcode;
|
||||
che->width = glyph->advance.x * scale;
|
||||
|
||||
BLI_ghash_insert(vfd->characters, POINTER_FROM_UINT(che->index), che);
|
||||
|
||||
/* Start converting the FT data */
|
||||
onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints");
|
||||
|
||||
/* Get number of on-curve points for bezier-triples (including conic virtual on-points). */
|
||||
for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
|
||||
const int n = ftoutline.contours[j] - contour_prev;
|
||||
contour_prev = ftoutline.contours[j];
|
||||
|
||||
for (k = 0; k < n; k++) {
|
||||
l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
|
||||
if (k == 0) {
|
||||
l_first = l;
|
||||
}
|
||||
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_On) {
|
||||
onpoints[j]++;
|
||||
}
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_On) {
|
||||
onpoints[j]++;
|
||||
}
|
||||
|
||||
{
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
|
||||
ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
|
||||
{
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
|
||||
ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
|
||||
onpoints[j]++;
|
||||
}
|
||||
onpoints[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* contour loop, bezier & conic styles merged */
|
||||
for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
|
||||
const int n = ftoutline.contours[j] - contour_prev;
|
||||
contour_prev = ftoutline.contours[j];
|
||||
/* contour loop, bezier & conic styles merged */
|
||||
for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
|
||||
const int n = ftoutline.contours[j] - contour_prev;
|
||||
contour_prev = ftoutline.contours[j];
|
||||
|
||||
/* add new curve */
|
||||
nu = (Nurb *)MEM_callocN(sizeof(Nurb), "objfnt_nurb");
|
||||
bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt");
|
||||
BLI_addtail(&che->nurbsbase, nu);
|
||||
/* add new curve */
|
||||
nu = (Nurb *)MEM_callocN(sizeof(Nurb), "objfnt_nurb");
|
||||
bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt");
|
||||
BLI_addtail(nurbsbase, nu);
|
||||
|
||||
nu->type = CU_BEZIER;
|
||||
nu->pntsu = onpoints[j];
|
||||
nu->resolu = 8;
|
||||
nu->flagu = CU_NURB_CYCLIC;
|
||||
nu->bezt = bezt;
|
||||
nu->type = CU_BEZIER;
|
||||
nu->pntsu = onpoints[j];
|
||||
nu->resolu = 8;
|
||||
nu->flagu = CU_NURB_CYCLIC;
|
||||
nu->bezt = bezt;
|
||||
|
||||
/* individual curve loop, start-end */
|
||||
for (k = 0; k < n; k++) {
|
||||
l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
|
||||
if (k == 0) {
|
||||
l_first = l;
|
||||
}
|
||||
/* individual curve loop, start-end */
|
||||
for (k = 0; k < n; k++) {
|
||||
l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
|
||||
if (k == 0) {
|
||||
l_first = l;
|
||||
}
|
||||
|
||||
/* virtual conic on-curve points */
|
||||
/* virtual conic on-curve points */
|
||||
{
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
|
||||
ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
|
||||
{
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
|
||||
ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
|
||||
dx = (ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f;
|
||||
dy = (ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f;
|
||||
|
||||
/* left handle */
|
||||
bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f;
|
||||
bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f;
|
||||
|
||||
/* midpoint (virtual on-curve point) */
|
||||
bezt->vec[1][0] = dx;
|
||||
bezt->vec[1][1] = dy;
|
||||
|
||||
/* right handle */
|
||||
bezt->vec[2][0] = (dx + (2 * ftoutline.points[l_next].x) * scale) / 3.0f;
|
||||
bezt->vec[2][1] = (dy + (2 * ftoutline.points[l_next].y) * scale) / 3.0f;
|
||||
|
||||
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||
bezt->radius = 1.0f;
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* on-curve points */
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_On) {
|
||||
const int l_prev = (k > 0) ? (l - 1) : ftoutline.contours[j];
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
dx = (ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f;
|
||||
dy = (ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f;
|
||||
|
||||
/* left handle */
|
||||
if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
|
||||
bezt->vec[0][0] = ftoutline.points[l_prev].x * scale;
|
||||
bezt->vec[0][1] = ftoutline.points[l_prev].y * scale;
|
||||
bezt->h1 = HD_FREE;
|
||||
}
|
||||
else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
|
||||
bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_prev].x)) * scale /
|
||||
3.0f;
|
||||
bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_prev].y)) * scale /
|
||||
3.0f;
|
||||
bezt->h1 = HD_FREE;
|
||||
}
|
||||
else {
|
||||
bezt->vec[0][0] = ftoutline.points[l].x * scale -
|
||||
(ftoutline.points[l].x - ftoutline.points[l_prev].x) * scale / 3.0f;
|
||||
bezt->vec[0][1] = ftoutline.points[l].y * scale -
|
||||
(ftoutline.points[l].y - ftoutline.points[l_prev].y) * scale / 3.0f;
|
||||
bezt->h1 = HD_VECT;
|
||||
}
|
||||
bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f;
|
||||
bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f;
|
||||
|
||||
/* midpoint (on-curve point) */
|
||||
bezt->vec[1][0] = ftoutline.points[l].x * scale;
|
||||
bezt->vec[1][1] = ftoutline.points[l].y * scale;
|
||||
/* midpoint (virtual on-curve point) */
|
||||
bezt->vec[1][0] = dx;
|
||||
bezt->vec[1][1] = dy;
|
||||
|
||||
/* right handle */
|
||||
if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
|
||||
bezt->vec[2][0] = ftoutline.points[l_next].x * scale;
|
||||
bezt->vec[2][1] = ftoutline.points[l_next].y * scale;
|
||||
bezt->h2 = HD_FREE;
|
||||
}
|
||||
else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
|
||||
bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_next].x)) * scale /
|
||||
3.0f;
|
||||
bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_next].y)) * scale /
|
||||
3.0f;
|
||||
bezt->h2 = HD_FREE;
|
||||
}
|
||||
else {
|
||||
bezt->vec[2][0] = ftoutline.points[l].x * scale -
|
||||
(ftoutline.points[l].x - ftoutline.points[l_next].x) * scale / 3.0f;
|
||||
bezt->vec[2][1] = ftoutline.points[l].y * scale -
|
||||
(ftoutline.points[l].y - ftoutline.points[l_next].y) * scale / 3.0f;
|
||||
bezt->h2 = HD_VECT;
|
||||
}
|
||||
bezt->vec[2][0] = (dx + (2 * ftoutline.points[l_next].x) * scale) / 3.0f;
|
||||
bezt->vec[2][1] = (dy + (2 * ftoutline.points[l_next].y) * scale) / 3.0f;
|
||||
|
||||
/* get the handles that are aligned, tricky...
|
||||
* - check if one of them is a vector handle.
|
||||
* - dist_squared_to_line_v2, check if the three beztriple points are on one line
|
||||
* - len_squared_v2v2, see if there's a distance between the three points
|
||||
* - len_squared_v2v2 again, to check the angle between the handles
|
||||
*/
|
||||
if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) &&
|
||||
(dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) <
|
||||
(0.001f * 0.001f)) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[2]) >
|
||||
max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]),
|
||||
len_squared_v2v2(bezt->vec[1], bezt->vec[2]))))
|
||||
{
|
||||
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||
}
|
||||
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||
bezt->radius = 1.0f;
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* on-curve points */
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_On) {
|
||||
const int l_prev = (k > 0) ? (l - 1) : ftoutline.contours[j];
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
|
||||
/* left handle */
|
||||
if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
|
||||
bezt->vec[0][0] = ftoutline.points[l_prev].x * scale;
|
||||
bezt->vec[0][1] = ftoutline.points[l_prev].y * scale;
|
||||
bezt->h1 = HD_FREE;
|
||||
}
|
||||
else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
|
||||
bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_prev].x)) * scale /
|
||||
3.0f;
|
||||
bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_prev].y)) * scale /
|
||||
3.0f;
|
||||
bezt->h1 = HD_FREE;
|
||||
}
|
||||
else {
|
||||
bezt->vec[0][0] = ftoutline.points[l].x * scale -
|
||||
(ftoutline.points[l].x - ftoutline.points[l_prev].x) * scale / 3.0f;
|
||||
bezt->vec[0][1] = ftoutline.points[l].y * scale -
|
||||
(ftoutline.points[l].y - ftoutline.points[l_prev].y) * scale / 3.0f;
|
||||
bezt->h1 = HD_VECT;
|
||||
}
|
||||
|
||||
/* midpoint (on-curve point) */
|
||||
bezt->vec[1][0] = ftoutline.points[l].x * scale;
|
||||
bezt->vec[1][1] = ftoutline.points[l].y * scale;
|
||||
|
||||
/* right handle */
|
||||
if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
|
||||
bezt->vec[2][0] = ftoutline.points[l_next].x * scale;
|
||||
bezt->vec[2][1] = ftoutline.points[l_next].y * scale;
|
||||
bezt->h2 = HD_FREE;
|
||||
}
|
||||
else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
|
||||
bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_next].x)) * scale /
|
||||
3.0f;
|
||||
bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_next].y)) * scale /
|
||||
3.0f;
|
||||
bezt->h2 = HD_FREE;
|
||||
}
|
||||
else {
|
||||
bezt->vec[2][0] = ftoutline.points[l].x * scale -
|
||||
(ftoutline.points[l].x - ftoutline.points[l_next].x) * scale / 3.0f;
|
||||
bezt->vec[2][1] = ftoutline.points[l].y * scale -
|
||||
(ftoutline.points[l].y - ftoutline.points[l_next].y) * scale / 3.0f;
|
||||
bezt->h2 = HD_VECT;
|
||||
}
|
||||
|
||||
/* get the handles that are aligned, tricky...
|
||||
* - check if one of them is a vector handle.
|
||||
* - dist_squared_to_line_v2, check if the three beztriple points are on one line
|
||||
* - len_squared_v2v2, see if there's a distance between the three points
|
||||
* - len_squared_v2v2 again, to check the angle between the handles
|
||||
*/
|
||||
if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) &&
|
||||
(dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) <
|
||||
(0.001f * 0.001f)) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[2]) >
|
||||
max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]),
|
||||
len_squared_v2v2(bezt->vec[1], bezt->vec[2]))))
|
||||
{
|
||||
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||
}
|
||||
bezt->radius = 1.0f;
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(onpoints);
|
||||
|
||||
return che;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
MEM_freeN(onpoints);
|
||||
}
|
||||
|
||||
static VChar *objchr_to_ftvfontdata(FT_Library library, VFont *vfont, FT_ULong charcode)
|
||||
static VChar *freetypechar_to_vchar(FT_Face face, FT_ULong charcode, const VFontData* vfd)
|
||||
Harley marked this conversation as resolved
Outdated
Campbell Barton
commented
`vfd` can be const.
|
||||
{
|
||||
VChar *che;
|
||||
|
||||
/* Freetype2 */
|
||||
FT_Face face;
|
||||
|
||||
/* Load the font to memory */
|
||||
if (vfont->temp_pf) {
|
||||
FT_Error err = FT_New_Memory_Face(
|
||||
library, vfont->temp_pf->data, vfont->temp_pf->size, 0, &face);
|
||||
if (err) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, charcode);
|
||||
if (FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) != FT_Err_Ok) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read the char */
|
||||
che = freetypechar_to_vchar(face, charcode, vfont->data);
|
||||
VChar *che = (VChar *)MEM_callocN(sizeof(struct VChar), "objfnt_char");
|
||||
freetype_outline_to_curves(face->glyph->outline, &che->nurbsbase, vfd->scale);
|
||||
che->index = charcode;
|
||||
che->width = face->glyph->advance.x * vfd->scale;
|
||||
BLI_ghash_insert(vfd->characters, POINTER_FROM_UINT(che->index), che);
|
||||
|
||||
/* And everything went ok */
|
||||
return che;
|
||||
}
|
||||
|
||||
|
@ -393,8 +349,6 @@ VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag)
|
|||
|
||||
VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, ulong character)
|
||||
{
|
||||
VChar *che = NULL;
|
||||
|
||||
if (!vfont) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -407,10 +361,17 @@ VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, ulong character)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
FT_Face face = vfont_face_load_from_packed_file(library, vfont->temp_pf);
|
||||
if (!face) {
|
||||
FT_Done_FreeType(library);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Load the character */
|
||||
che = objchr_to_ftvfontdata(library, vfont, character);
|
||||
VChar *che = freetypechar_to_vchar(face, character, vfont->data);
|
||||
|
||||
/* Free Freetype */
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
|
||||
return che;
|
||||
|
|
Loading…
Reference in New Issue
scale can be const.