diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_curve.py | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/font.c | 81 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_vfontdata.h | 3 | ||||
-rw-r--r-- | source/blender/blenlib/intern/freetypefont.c | 17 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curve_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_curve.c | 2 |
6 files changed, 83 insertions, 30 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 671cff4ebb4..9ba6bc70892 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -398,12 +398,13 @@ class DATA_PT_paragraph_alignment(CurveButtonsPanelText, Panel): def draw(self, context): layout = self.layout - layout.use_property_split = False + layout.use_property_split = True text = context.curve - layout.row().prop(text, "align_x", expand=True) - layout.row().prop(text, "align_y", expand=True) + col = layout.column() + col.prop(text, "align_x", text="Horizontal") + col.prop(text, "align_y", text="Vertical") class DATA_PT_paragraph_spacing(CurveButtonsPanelText, Panel): diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index b5fba6d30e8..31de8d8d51e 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -635,6 +635,22 @@ 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 ASCENT(vfd) ((vfd)->ascender * (vfd)->em_height) +#define DESCENT(vfd) ((vfd)->em_height - ASCENT(vfd)) + 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,26 +1035,30 @@ 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. */ + const float textbox_y_origin = 1.0f; - 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); + switch (cu->align_y) { + case CU_ALIGN_Y_TOP_BASELINE: + break; + case CU_ALIGN_Y_TOP: + yoff = textbox_y_origin - ASCENT(vfd); + break; + case CU_ALIGN_Y_CENTER: + yoff = ((((vfd->em_height + (lnr - 1) * linedist) * 0.5f) - ASCENT(vfd)) - + (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(vfd); + break; } ct = ct_textbox; @@ -1049,18 +1069,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(vfd); + break; + case CU_ALIGN_Y_CENTER: + yoff = ((vfd->em_height + (lnr - 1) * linedist) * 0.5f) - ASCENT(vfd); + break; + case CU_ALIGN_Y_BOTTOM_BASELINE: + yoff = (lnr - 1) * linedist; + break; + case CU_ALIGN_Y_BOTTOM: + yoff = (lnr - 1) * linedist + DESCENT(vfd); + break; } for (i = 0; i <= slen; i++) { @@ -1339,6 +1366,8 @@ finally: #undef MARGIN_Y_MIN } +#undef DESCENT +#undef ASCENT 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..892d084f5ee 100644 --- a/source/blender/blenlib/BLI_vfontdata.h +++ b/source/blender/blenlib/BLI_vfontdata.h @@ -43,6 +43,9 @@ typedef struct VFontData { struct GHash *characters; char name[128]; float scale; + /* Calculated from the font. */ + 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..3f3868bea45 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -359,10 +359,27 @@ 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) && + (face->ascender != face->descender); + + 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} }; |