Text3d: fix font family feature for unicode and correct tooltip
authorCampbell Barton <ideasman42@gmail.com>
Sun, 5 Jan 2014 14:33:45 +0000 (01:33 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 5 Jan 2014 14:37:19 +0000 (01:37 +1100)
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/font.c
source/blender/editors/curve/editfont.c
source/blender/editors/object/object_edit.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesrna/intern/rna_curve.c

index 9c6a28d674fc80e523249fd2084cb456248c7c8f..1d52aa6edcc9026adf695b2f31c8b81abd0f2ef7 100644 (file)
@@ -83,11 +83,17 @@ void BKE_vfont_free(struct VFont *sc);
 struct VFont *BKE_vfont_builtin_get(void);
 struct VFont *BKE_vfont_load(struct Main *bmain, const char *name);
 
-bool BKE_vfont_to_curve_nubase(struct Main *bmain, struct Scene *scene, struct Object *ob,
-                               struct ListBase *nubase, int mode, struct CharTrans **r_chartransdata);
-
-bool BKE_vfont_to_curve(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode,
-                        struct CharTrans **r_chartransdata);
+bool BKE_vfont_to_curve_nubase_ex(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode,
+                                  struct ListBase *r_nubase,
+                                  const wchar_t **r_text, int *r_text_len, bool *r_text_free,
+                                     struct CharTrans **r_chartransdata);
+bool BKE_vfont_to_curve_nubase(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode,
+                                  struct ListBase *r_nubase);
+
+bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode,
+                           const wchar_t **r_text, int *r_text_len, bool *r_text_free,
+                           struct CharTrans **r_chartransdata);
+bool BKE_vfont_to_curve(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode);
 
 int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
 
index 7ae7fb3a9a0705cadc374727f86188ba88561ec8..a84ce5677b03ed669518c0fa0277693d204b1e3d 100644 (file)
@@ -1586,36 +1586,50 @@ static void new_particle_duplilist(EvaluationContext *eval_ctx,
        }
 }
 
-static Object *find_family_object(Object **obar, char *family, char ch)
+static Object *find_family_object(const char *family, size_t family_len, unsigned int ch, GHash *family_gh)
 {
+       Object **ob_pt;
        Object *ob;
-       int flen;
-       
-       if (obar[(int)ch]) return obar[(int)ch];
-       
-       flen = strlen(family);
-       
-       ob = G.main->object.first;
-       while (ob) {
-               if (ob->id.name[flen + 2] == ch) {
-                       if (strncmp(ob->id.name + 2, family, flen) == 0) break;
+       void *ch_key = SET_UINT_IN_POINTER(ch);
+
+       if ((ob_pt = (Object **)BLI_ghash_lookup_p(family_gh, ch_key))) {
+               ob = *ob_pt;
+       }
+       else {
+               char ch_utf8[7];
+               size_t ch_utf8_len;
+
+               ch_utf8_len = BLI_str_utf8_from_unicode(ch, ch_utf8);
+               ch_utf8[ch_utf8_len] = '\0';
+               ch_utf8_len += 1;  /* compare with null terminator */
+
+               for (ob = G.main->object.first; ob; ob = ob->id.next) {
+                       if (STREQLEN(ob->id.name + 2 + family_len, ch_utf8, ch_utf8_len)) {
+                               if (STREQLEN(ob->id.name + 2, family, family_len)) {
+                                       break;
+                               }
+                       }
                }
-               ob = ob->id.next;
+
+               /* inserted value can be NULL, just to save searches in future */
+               BLI_ghash_insert(family_gh, ch_key, ob);
        }
-       
-       obar[(int)ch] = ob;
-       
+
        return ob;
 }
 
 
 static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persistent_id[MAX_DUPLI_RECUR], int level, short flag)
 {
-       Object *ob, *obar[256] = {NULL};
+       GHash *family_gh;
+       Object *ob;
        Curve *cu;
        struct CharTrans *ct, *chartransdata = NULL;
        float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
-       int slen, a;
+       int text_len, a;
+       size_t family_len;
+       const wchar_t *text = NULL;
+       bool text_free = false;
        
        /* simple preventing of too deep nested groups */
        if (level > MAX_DUPLI_RECUR) return;
@@ -1624,20 +1638,28 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persiste
        
        /* in par the family name is stored, use this to find the other objects */
        
-       BKE_vfont_to_curve(G.main, scene, par, FO_DUPLI, &chartransdata);
-       if (chartransdata == NULL) return;
+       BKE_vfont_to_curve_ex(G.main, scene, par, FO_DUPLI,
+                             &text, &text_len, &text_free, &chartransdata);
+
+       if (text == NULL || chartransdata == NULL) {
+               return;
+       }
 
        cu = par->data;
-       slen = strlen(cu->str);
        fsize = cu->fsize;
        xof = cu->xof;
        yof = cu->yof;
        
        ct = chartransdata;
        
-       for (a = 0; a < slen; a++, ct++) {
+       /* cache result */
+       family_len = strlen(cu->family);
+       family_gh = BLI_ghash_int_new_ex(__func__, 256);
+
+       /* advance matching BLI_strncpy_wchar_from_utf8 */
+       for (a = 0; a < text_len; a++, ct++) {
                
-               ob = find_family_object(obar, cu->family, cu->str[a]);
+               ob = find_family_object(cu->family, family_len, text[a], family_gh);
                if (ob) {
                        vec[0] = fsize * (ct->xof - xof);
                        vec[1] = fsize * (ct->yof - yof);
@@ -1651,7 +1673,13 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persiste
                        new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIVERTS, flag);
                }
        }
-       
+
+       if (text_free) {
+               MEM_freeN((void *)text);
+       }
+
+       BLI_ghash_free(family_gh, NULL, NULL);
+
        MEM_freeN(chartransdata);
 }
 
index 4282e860c4e04fbc154bec1f7ae08519b66c564b..da386e41ded03fc73fda17419c0a1ec77920edc5 100644 (file)
@@ -1375,7 +1375,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
                ob->curve_cache->path = NULL;
 
                if (ob->type == OB_FONT) {
-                       BKE_vfont_to_curve_nubase(G.main, scene, ob, &nubase, FO_EDIT, NULL);
+                       BKE_vfont_to_curve_nubase(G.main, scene, ob, FO_EDIT, &nubase);
                }
                else {
                        BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu));
index 2a5f8cb804135984c0f9e99f533082912c3a0e03..1d268b7d7ceb86f9b0feac3cff1d3833caba7bad 100644 (file)
@@ -495,8 +495,10 @@ static float char_width(Curve *cu, VChar *che, CharInfo *info)
        }
 }
 
-bool BKE_vfont_to_curve_nubase(Main *bmain, Scene *scene, Object *ob, ListBase *nubase,
-                               int mode, struct CharTrans **r_chartransdata)
+bool BKE_vfont_to_curve_nubase_ex(Main *bmain, Scene *scene, Object *ob, int mode,
+                                  ListBase *r_nubase,
+                                  const wchar_t **r_text, int *r_text_len, bool *r_text_free,
+                                  struct CharTrans **r_chartransdata)
 {
        Curve *cu = ob->data;
        EditFont *ef = cu->editfont;
@@ -1020,7 +1022,7 @@ makebreak:
 
        if (mode == FO_EDIT) {
                /* make nurbdata */
-               BKE_nurbList_free(nubase);
+               BKE_nurbList_free(r_nubase);
                
                ct = chartransdata;
                for (i = 0; i < slen; i++) {
@@ -1037,7 +1039,7 @@ makebreak:
                        }
                        /* We do not want to see any character for \n or \r */
                        if (cha != '\n' && cha != '\r')
-                               buildchar(bmain, cu, nubase, cha, info, ct->xof, ct->yof, ct->rot, i);
+                               buildchar(bmain, cu, r_nubase, 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;
@@ -1054,7 +1056,7 @@ makebreak:
 
                                twidth = char_width(cu, che, info);
                                ulwidth = cu->fsize * ((twidth * (1.0f + (info->kern / 40.0f))) + uloverlap);
-                               build_underline(cu, nubase,
+                               build_underline(cu, r_nubase,
                                                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,
@@ -1068,8 +1070,18 @@ makebreak:
 
 finally:
 
-       if (ef == NULL)
-               MEM_freeN((void *)mem);
+       {
+               if (r_text) {
+                       *r_text = mem;
+                       *r_text_len = slen;
+                       *r_text_free = (ef == NULL);
+               }
+               else {
+                       if (ef == NULL) {
+                               MEM_freeN((void *)mem);
+                       }
+               }
+       }
 
        if (chartransdata) {
                if (ok && r_chartransdata) {
@@ -1083,12 +1095,33 @@ finally:
        return ok;
 }
 
-bool BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode,
-                        struct CharTrans **r_chartransdata)
+
+bool BKE_vfont_to_curve_nubase(Main *bmain, Scene *scene, Object *ob, int mode,
+                               ListBase *r_nubase)
+{
+       BLI_assert(ob->type == OB_FONT);
+
+       return BKE_vfont_to_curve_nubase_ex(bmain, scene, ob, mode,
+                                           r_nubase,
+                                           NULL, NULL, NULL, NULL);
+}
+
+bool BKE_vfont_to_curve_ex(Main *bmain, Scene *scene, Object *ob, int mode,
+                           const wchar_t **r_text, int *r_text_len, bool *r_text_free,
+                           struct CharTrans **r_chartransdata)
 {
        Curve *cu = (Curve *) ob->data;
 
        BLI_assert(ob->type == OB_FONT);
 
-       return BKE_vfont_to_curve_nubase(bmain, scene, ob, &cu->nurb, mode, r_chartransdata);
+       return BKE_vfont_to_curve_nubase_ex(bmain, scene, ob, mode,
+                                           &cu->nurb,
+                                           r_text, r_text_len, r_text_free, r_chartransdata);
+}
+
+
+bool BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode)
+{
+       return BKE_vfont_to_curve_ex(bmain, scene, ob, mode,
+                                    NULL, NULL, NULL, NULL);
 }
index 2263c69b71289aaa4064bce8a4db123ffdba5e81..1fbd3a0f9f5910de27298ac9fae299038d8d5f27 100644 (file)
@@ -264,7 +264,7 @@ static void text_update_edited(bContext *C, Scene *scene, Object *obedit, const
                }
        }
 
-       BKE_vfont_to_curve(bmain, scene, obedit, mode, NULL);
+       BKE_vfont_to_curve(bmain, scene, obedit, mode);
 
        if (recalc)
                DAG_id_tag_update(obedit->data, 0);
@@ -1037,7 +1037,7 @@ static int move_cursor(bContext *C, int type, int select)
                if (ef->selstart) {
                        struct Main *bmain = CTX_data_main(C);
                        ef->selstart = ef->selend = 0;
-                       BKE_vfont_to_curve(bmain, scene, obedit, FO_SELCHANGE, NULL);
+                       BKE_vfont_to_curve(bmain, scene, obedit, FO_SELCHANGE);
                }
        }
 
index 82b6f15dc3898f1a5fd3718a01a9bd444e494445..f7fb2a29cdbbe72aaa86e769c5227cff9688f94f 100644 (file)
@@ -930,9 +930,6 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
                                                if (cu1->vfontbi) cu1->vfontbi->id.us--;
                                                cu1->vfontbi = cu->vfontbi;
                                                id_us_plus((ID *)cu1->vfontbi);
-
-                                               BKE_vfont_to_curve(bmain, scene, base->object, FO_EDIT, NULL); /* needed? */
-
                                                
                                                BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
                                                
index 2cc56d49ff8b2922152dbeee727cf158b091d9ff..adcc4af41e0f6f2092ad8487554afe88d425a49a 100644 (file)
@@ -212,10 +212,6 @@ typedef struct Curve {
        void *lastsel;
        
        /* font part */
-       /* WARNING: cu->len is...
-        * - strlen(cu->str) object-mode (bytes).
-        * - BLI_strlen_utf8(cu->str) in edit-mode.
-        * This should be cleaned up and some point, see 'write_curves' - campbell */
        short lines;
        char spacemode, pad1;
        float spacing, linedist, shear, fsize, wordspace, ulpos, ulheight;
@@ -235,7 +231,7 @@ typedef struct Curve {
        int selstart, selend;
        int pad2;
 
-       char family[24];
+       char family[64];
        struct VFont *vfont;
        struct VFont *vfontb;
        struct VFont *vfonti;
index bb1246006863b11136e16014e967d930c9ef43a5..8aacfe470eab283de1ea99462071c4b7c34df4db 100644 (file)
@@ -1009,9 +1009,9 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
        prop = RNA_def_property(srna, "family", PROP_STRING, PROP_NONE);
        RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2);
        RNA_def_property_ui_text(prop, "Object Font",
-                                "Use Blender Objects as font characters (give font objects a common name "
-                                "followed by the character they represent, eg. family_a, family_b, etc, "
-                                "and turn on Verts Duplication)");
+                                "Use Objects as font characters (give font objects a common name "
+                                "followed by the character they represent, eg. 'family_a', 'family_b', etc, "
+                                "and set this to 'family_', turn on Vertex Duplication)");
        RNA_def_property_update(prop, 0, "rna_Curve_update_data");
        
        prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE);