[Bf-blender-cvs] [50253272bcd] experimental-build: Fixes for font vertical alignment + fallback for internal font

Dalai Felinto noreply at git.blender.org
Fri Aug 31 23:40:42 CEST 2018


Commit: 50253272bcd655751bbc9abd286c80ddd0299fdd
Author: Dalai Felinto
Date:   Fri Aug 31 18:40:02 2018 -0300
Branches: experimental-build
https://developer.blender.org/rB50253272bcd655751bbc9abd286c80ddd0299fdd

Fixes for font vertical alignment + fallback for internal font

===================================================================

M	source/blender/blenkernel/intern/font.c
M	source/blender/blenlib/BLI_vfontdata.h
M	source/blender/blenlib/intern/freetypefont.c
M	source/blender/makesdna/DNA_curve_types.h
M	source/blender/makesrna/intern/rna_curve.c

===================================================================

diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index b5fba6d30e8..45a581324a8 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -635,6 +635,23 @@ struct TempLineInfo {
 	int   wspace_nr;  /* number of whitespaces of line */
 };
 
+/**
+ * Font metric values explained:
+ *
+ * Baseline: Line where the text "rests", used as the origin vertical position for the glyphs.
+ * Em height: Space most glyphs should fit within.
+ * Ascent: the recommended distance above the baseline to fit most characters.
+ * Descent: the recommended distance below the baseline to fit most characters.
+ *
+ * We obtain ascent and descent from the font itself (FT_Face->ascender / face->height).
+ * And in some cases it is even the same value as FT_Face->bbox.yMax/yMin (font top and bottom respectively).
+ *
+ * The em_height here is relative to FT_Face->bbox.
+*/
+#define EM_HEIGHT vfd->em_height
+#define ASCENT vfd->ascender * EM_HEIGHT
+#define DESCENT EM_HEIGHT - ASCENT
+
 bool BKE_vfont_to_curve_ex(Object *ob, Curve *cu, int mode, ListBase *r_nubase,
                            const wchar_t **r_text, int *r_text_len, bool *r_text_free,
                            struct CharTrans **r_chartransdata)
@@ -1019,27 +1036,33 @@ makebreak:
 	/* 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 */
+			if (i_textbox < slen) {
+				/* All previous textboxes are 'full', only align the last used text-box. */
+				struct CharTrans *ct_textbox = chartransdata + i_textbox;
 				float yoff = 0.0f;
-				int lines;
-				struct CharTrans *ct_last, *ct_textbox;
 
-				ct_last = chartransdata + slen - 1;
-				ct_textbox = chartransdata + i_textbox;
+/* The initial Y origin of the textbox is harcoded to 1.0f * text scale. */
+#define TEXTBOX_Y_ORIGIN 1.0f
 
-				lines = ct_last->linenr - ct_textbox->linenr + 1;
-				if (mem[slen - 1] == '\n') {
-					lines++;
+				switch (cu->align_y) {
+					case CU_ALIGN_Y_TOP_BASELINE:
+						break;
+					case CU_ALIGN_Y_TOP:
+						yoff = TEXTBOX_Y_ORIGIN - ASCENT;
+						break;
+					case CU_ALIGN_Y_CENTER:
+						yoff = (((EM_HEIGHT + (lnr - 1) * linedist) * 0.5f) - ASCENT)
+						       -(tb_scale.h  * 0.5f) + TEXTBOX_Y_ORIGIN;
+						break;
+					case CU_ALIGN_Y_BOTTOM_BASELINE:
+						yoff = TEXTBOX_Y_ORIGIN + ((lnr - 1) * linedist) - tb_scale.h;
+						break;
+					case CU_ALIGN_Y_BOTTOM:
+						yoff = TEXTBOX_Y_ORIGIN + ((lnr - 1) * linedist) - tb_scale.h + DESCENT;
+						break;
 				}
 
-				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);
-				}
+#undef TEXTBOX_Y_ORIGIN
 
 				ct = ct_textbox;
 				for (i = i_textbox - 1; i < slen; i++) {
@@ -1049,18 +1072,25 @@ makebreak:
 			}
 		}
 		else {
-			/* non text-box case handled separately */
+			/* Non text-box case handled separately. */
 			ct = chartransdata;
 			float yoff = 0.0f;
 
-			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;
+			switch (cu->align_y) {
+				case CU_ALIGN_Y_TOP_BASELINE:
+					break;
+				case CU_ALIGN_Y_TOP:
+					yoff = -ASCENT;
+					break;
+				case CU_ALIGN_Y_CENTER:
+					yoff = ((EM_HEIGHT + (lnr - 1) * linedist) * 0.5f) - ASCENT;
+					break;
+				case CU_ALIGN_Y_BOTTOM_BASELINE:
+					yoff = (lnr - 1) * linedist;
+					break;
+				case CU_ALIGN_Y_BOTTOM:
+					yoff = (lnr - 1) * linedist + DESCENT;
+					break;
 			}
 
 			for (i = 0; i <= slen; i++) {
@@ -1339,6 +1369,9 @@ finally:
 #undef MARGIN_Y_MIN
 }
 
+#undef DESCENT
+#undef ASCENT
+#undef EM_HEIGHT
 
 bool BKE_vfont_to_curve_nubase(Object *ob, int mode, ListBase *r_nubase)
 {
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
index 1cc1ef17486..b1732da2aad 100644
--- a/source/blender/blenlib/BLI_vfontdata.h
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -43,6 +43,8 @@ typedef struct VFontData {
 	struct GHash *characters;
 	char name[128];
 	float scale;
+	float em_height;
+	float ascender;
 } VFontData;
 
 typedef struct VChar {
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index c7604b3cd6d..afc34037e88 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -359,10 +359,26 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
 		lcode = charcode = FT_Get_First_Char(face, &glyph_index);
 	}
 
+	/* Blender default BFont is not "complete". */
+	const bool complete_font = ((face->ascender != 0) && (face->descender != 0));
+
+	if (complete_font) {
+		/* We can get descender as well, but we simple store descender in relation to the ascender.
+		 * Also note that descender is stored as a negative number. */
+		vfd->ascender = (float)face->ascender / (face->ascender - face->descender);
+	}
+	else {
+		vfd->ascender = 0.8f;
+		vfd->em_height = 1.0f;
+	}
 
 	/* Adjust font size */
 	if (face->bbox.yMax != face->bbox.yMin) {
 		vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin));
+
+		if (complete_font) {
+			vfd->em_height = (float)(face->ascender - face->descender) / (face->bbox.yMax - face->bbox.yMin);
+		}
 	}
 	else {
 		vfd->scale = 1.0f / 1000.0f;
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 6e3573b9f80..7c7eaae4949 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -334,7 +334,8 @@ enum {
 	CU_ALIGN_Y_TOP_BASELINE       = 0,
 	CU_ALIGN_Y_TOP                = 1,
 	CU_ALIGN_Y_CENTER             = 2,
-	CU_ALIGN_Y_BOTTOM             = 3,
+	CU_ALIGN_Y_BOTTOM_BASELINE    = 3,
+	CU_ALIGN_Y_BOTTOM             = 4,
 };
 
 /* Nurb.flag */
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 6b294b9b3cd..a90a5cdff90 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -969,6 +969,8 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
 		{CU_ALIGN_Y_TOP, "TOP", 0, "Top", "Align text to the top"},
 		{CU_ALIGN_Y_CENTER, "CENTER", 0, "Center", "Align text to the middle"},
 		{CU_ALIGN_Y_BOTTOM, "BOTTOM", 0, "Bottom", "Align text to the bottom"},
+		{CU_ALIGN_Y_BOTTOM_BASELINE, "BOTTOM_BASELINE", 0, "Bottom Base-Line",
+		"Align text to the bottom but use the base-line of the text"},
 		{0, NULL, 0, NULL, NULL}
 	};



More information about the Bf-blender-cvs mailing list