Text Object: Vertical Alignment
authorDalai Felinto <dfelinto@gmail.com>
Tue, 21 Jun 2016 02:21:24 +0000 (23:21 -0300)
committerDalai Felinto <dfelinto@gmail.com>
Tue, 21 Jun 2016 02:21:24 +0000 (23:21 -0300)
A new option for Font/Text objects vertical alignment:

* Top Base-Line (current mode)
* Top
* Center
* Bottom

The Top is the equivalent as the Top-Baseline with an empty line at the begin of the
text. It's nice to have this option too though, since if we are driving
the alignment via Python we don't want to add extra lines to the text
only to accomodate to the desired vertical alignment.

The Center and Bottom are as intuitive as their name suggest.

When working with text boxes, the vertical alignment only work for
paragraphs that are not vertically full.

Many thanks to Campbell Barton (ideasman42 / @campbellbarton) for the
code review, code comments, and overall suggestions and changes :)

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D2061

release/scripts/startup/bl_ui/properties_data_curve.py
source/blender/blenkernel/intern/font.c
source/blender/editors/object/object_edit.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesrna/intern/rna_curve.c

index 81ecd2e8db57d4bdb2fe82a7c80e23db3b72a134..af8431ba1dc7dd98fd4a158ba885cbf77abaa61f 100644 (file)
@@ -370,8 +370,11 @@ class DATA_PT_paragraph(CurveButtonsPanelText, Panel):
 
         text = context.curve
 
-        layout.label(text="Align:")
-        layout.prop(text, "align", expand=True)
+        layout.label(text="Horizontal Alignment:")
+        layout.prop(text, "align_x", expand=True)
+
+        layout.label(text="Vertical Alignment:")
+        layout.prop(text, "align_y", expand=True)
 
         split = layout.split()
 
index 98757407e89be33b8555f473f54d102226e3d6b2..b4088934ea4459250a8bc5197e352c8eae468e28 100644 (file)
@@ -628,6 +628,8 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
        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;
@@ -830,6 +832,7 @@ makebreak:
                            (cu->totbox > (curbox + 1)) &&
                            ((-(yof - tb_scale.y)) > (tb_scale.h - linedist) - yof_scale))
                        {
+                               i_textbox = i + 1;
                                maxlen = 0;
                                curbox++;
 
@@ -983,6 +986,60 @@ 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 */
+                               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);
 
        /* TEXT ON CURVE */
index 06200778ee5fe32918437a51d149abdce4e21c18..01a567931b3a7797086721c1468d9ddde72eed98 100644 (file)
@@ -946,6 +946,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
                                                cu1 = base->object->data;
 
                                                cu1->spacemode = cu->spacemode;
+                                               cu1->align_y = cu->align_y;
                                                cu1->spacing = cu->spacing;
                                                cu1->linedist = cu->linedist;
                                                cu1->shear = cu->shear;
index 8f711c1b23bf9b1f97667484b932b683f8b82888..6d139955ae1ffa7621a1673b6f8304a66a63b093 100644 (file)
@@ -230,7 +230,7 @@ typedef struct Curve {
 
        /* font part */
        short lines;
-       char spacemode, pad1;
+       char spacemode, align_y;
        float spacing, linedist, shear, fsize, wordspace, ulpos, ulheight;
        float xof, yof;
        float linewidth;
@@ -329,6 +329,14 @@ enum {
        CU_FLUSH              = 4,
 };
 
+/* Curve.align_y */
+enum {
+       CU_ALIGN_Y_TOP_BASELINE       = 0,
+       CU_ALIGN_Y_TOP                = 1,
+       CU_ALIGN_Y_CENTER             = 2,
+       CU_ALIGN_Y_BOTTOM             = 3,
+};
+
 /* Nurb.flag */
 enum {
        CU_SMOOTH             = 1 << 0,
index cb7a40a9238c3a4a4c5f810859a04e81939b59db..b18fbf962bbf81bc5adf6a35b704bbf18e70588c 100644 (file)
@@ -952,7 +952,7 @@ static void rna_def_nurbs(BlenderRNA *UNUSED(brna), StructRNA *srna)
 static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
 {
        PropertyRNA *prop;
-       
+
        static EnumPropertyItem prop_align_items[] = {
                {CU_LEFT, "LEFT", 0, "Left", "Align text to the left"},
                {CU_MIDDLE, "CENTER", 0, "Center", "Center text"},
@@ -961,14 +961,28 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
                {CU_FLUSH, "FLUSH", 0, "Flush", "Align to the left and the right, with equal character spacing"},
                {0, NULL, 0, NULL, NULL}
        };
-               
+
+       static EnumPropertyItem prop_align_y_items[] = {
+               {CU_ALIGN_Y_TOP_BASELINE, "TOP_BASELINE", 0, "Top Base-Line", "Align to top but use the base-line of the text"},
+               {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"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        /* Enums */
-       prop = RNA_def_property(srna, "align", PROP_ENUM, PROP_NONE);
+       prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "spacemode");
        RNA_def_property_enum_items(prop, prop_align_items);
-       RNA_def_property_ui_text(prop, "Text Align", "Text align from the object center");
+       RNA_def_property_ui_text(prop, "Text Horizontal Align", "Text horizontal align from the object center");
        RNA_def_property_update(prop, 0, "rna_Curve_update_data");
-       
+
+       prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "align_y");
+       RNA_def_property_enum_items(prop, prop_align_y_items);
+       RNA_def_property_ui_text(prop, "Text Vertical Align", "Text vertical align from the object center");
+       RNA_def_property_update(prop, 0, "rna_Curve_update_data");
+
        /* number values */
        prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "fsize");