Revert to master - those changes are globally valid, but remain incomplete,
[blender.git] / source / blender / blenkernel / intern / font.c
index 23e0a66621317bb28afb65472049637e1608b8d6..e3ebb7f908ce96a54100044031baff4d93abe598 100644 (file)
@@ -203,7 +203,7 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
        return vfont->data;
 }
 
-VFont *BKE_vfont_load(Main *bmain, const char *name)
+VFont *BKE_vfont_load(Main *bmain, const char *filepath)
 {
        char filename[FILE_MAXFILE];
        VFont *vfont = NULL;
@@ -211,16 +211,16 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
        PackedFile *temp_pf = NULL;
        bool is_builtin;
        
-       if (STREQ(name, FO_BUILTIN_NAME)) {
-               BLI_strncpy(filename, name, sizeof(filename));
+       if (STREQ(filepath, FO_BUILTIN_NAME)) {
+               BLI_strncpy(filename, filepath, sizeof(filename));
                
                pf = get_builtin_packedfile();
                is_builtin = true;
        }
        else {
-               BLI_split_file_part(name, filename, sizeof(filename));
-               pf = newPackedFile(NULL, name, bmain->name);
-               temp_pf = newPackedFile(NULL, name, bmain->name);
+               BLI_split_file_part(filepath, filename, sizeof(filename));
+               pf = newPackedFile(NULL, filepath, bmain->name);
+               temp_pf = newPackedFile(NULL, filepath, bmain->name);
                
                is_builtin = false;
        }
@@ -237,7 +237,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
                        if (vfd->name[0] != '\0') {
                                BLI_strncpy(vfont->id.name + 2, vfd->name, sizeof(vfont->id.name) - 2);
                        }
-                       BLI_strncpy(vfont->name, name, sizeof(vfont->name));
+                       BLI_strncpy(vfont->name, filepath, sizeof(vfont->name));
 
                        /* if autopack is on store the packedfile in de font structure */
                        if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
@@ -245,7 +245,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
                        }
 
                        /* Do not add FO_BUILTIN_NAME to temporary listbase */
-                       if (strcmp(filename, FO_BUILTIN_NAME)) {
+                       if (!STREQ(filename, FO_BUILTIN_NAME)) {
                                vfont->temp_pf = temp_pf;
                        }
                }
@@ -259,6 +259,37 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
        return vfont;
 }
 
+VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists)
+{
+       VFont *vfont;
+       char str[FILE_MAX], strtest[FILE_MAX];
+
+       BLI_strncpy(str, filepath, sizeof(str));
+       BLI_path_abs(str, bmain->name);
+
+       /* first search an identical filepath */
+       for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) {
+               BLI_strncpy(strtest, vfont->name, sizeof(vfont->name));
+               BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &vfont->id));
+
+               if (BLI_path_cmp(strtest, str) == 0) {
+                       vfont->id.us++;  /* officially should not, it doesn't link here! */
+                       if (r_exists)
+                               *r_exists = true;
+                       return vfont;
+               }
+       }
+
+       if (r_exists)
+               *r_exists = false;
+       return BKE_vfont_load(bmain, filepath);
+}
+
+VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath)
+{
+       return BKE_vfont_load_exists_ex(bmain, filepath, NULL);
+}
+
 static VFont *which_vfont(Curve *cu, CharInfo *info)
 {
        switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {
@@ -484,26 +515,53 @@ int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
 {
        Curve *cu = ob->data;
        EditFont *ef = cu->editfont;
+       int start, end, direction;
        
        if ((ob->type != OB_FONT) || (ef == NULL)) return 0;
 
+       BLI_assert(ef->len >= 0);
        BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1);
-       BLI_assert(ef->selend   >= 0 && ef->selend   <= ef->len + 1);
+       BLI_assert(ef->selend   >= 0 && ef->selend   <= ef->len);
        BLI_assert(ef->pos      >= 0 && ef->pos      <= ef->len);
 
-       if (ef->selstart == 0) return 0;
+       if (ef->selstart == 0) {
+               return 0;
+       }
+
        if (ef->selstart <= ef->selend) {
-               *r_start = ef->selstart - 1;
-               *r_end = ef->selend - 1;
-               return 1;
+               start = ef->selstart - 1;
+               end = ef->selend - 1;
+               direction = 1;
+       }
+       else {
+               start = ef->selend;
+               end = ef->selstart - 2;
+               direction = -1;
+       }
+
+       if (start == end + 1) {
+               return 0;
        }
        else {
-               *r_start = ef->selend;
-               *r_end = ef->selstart - 2;
-               return -1;
+               BLI_assert(start < end + 1);
+               *r_start = start;
+               *r_end = end;
+               return direction;
        }
 }
 
+void BKE_vfont_select_clamp(Object *ob)
+{
+       Curve *cu = ob->data;
+       EditFont *ef = cu->editfont;
+
+       BLI_assert((ob->type == OB_FONT) && ef);
+
+       CLAMP_MAX(ef->pos,      ef->len);
+       CLAMP_MAX(ef->selstart, ef->len + 1);
+       CLAMP_MAX(ef->selend,   ef->len);
+}
+
 static float char_width(Curve *cu, VChar *che, CharInfo *info)
 {
        /* The character wasn't found, propably ascii = 0, then the width shall be 0 as well */
@@ -518,6 +576,14 @@ static float char_width(Curve *cu, VChar *che, CharInfo *info)
        }
 }
 
+static void textbox_scale(TextBox *tb_dst, const TextBox *tb_src, float scale)
+{
+       tb_dst->x = tb_src->x * scale;
+       tb_dst->y = tb_src->y * scale;
+       tb_dst->w = tb_src->w * scale;
+       tb_dst->h = tb_src->h * scale;
+}
+
 /**
  * Used for storing per-line data for alignment & wrapping.
  */
@@ -538,7 +604,8 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
        VFont *vfont, *oldvfont;
        VFontData *vfd = NULL;
        CharInfo *info = NULL, *custrinfo;
-       TextBox *tb;
+       TextBox tb_scale;
+       bool use_textbox;
        VChar *che;
        struct CharTrans *chartransdata = NULL, *ct;
        struct TempLineInfo *lineinfo;
@@ -551,6 +618,11 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
        const wchar_t *mem;
        wchar_t ascii;
        bool ok = false;
+       const float xof_scale = cu->xof / cu->fsize;
+       const float yof_scale = cu->yof / cu->fsize;
+
+#define MARGIN_X_MIN (xof_scale + tb_scale.x)
+#define MARGIN_Y_MIN (yof_scale + tb_scale.y)
 
        /* remark: do calculations including the trailing '\0' of a string
         * because the cursor can be at that location */
@@ -613,8 +685,13 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
        
        linedist = cu->linedist;
        
-       xof = cu->xof + (cu->tb[0].x / cu->fsize);
-       yof = cu->yof + (cu->tb[0].y / cu->fsize);
+       curbox = 0;
+       textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / cu->fsize);
+       use_textbox = (tb_scale.w != 0.0f);
+
+
+       xof = MARGIN_X_MIN;
+       yof = MARGIN_Y_MIN;
 
        xtrax = 0.5f * cu->spacing - 0.5f;
 
@@ -624,8 +701,6 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
                custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK);
        }
 
-       tb = &(cu->tb[0]);
-       curbox = 0;
        for (i = 0; i <= slen; i++) {
 makebreak:
                /* Characters in the list */
@@ -651,6 +726,7 @@ makebreak:
                if (!vfd) {
                        MEM_freeN(chartransdata);
                        chartransdata = NULL;
+                       MEM_freeN(lineinfo);
                        goto finally;
                }
 
@@ -685,9 +761,9 @@ makebreak:
                twidth = char_width(cu, che, info);
 
                /* Calculate positions */
-               if ((tb->w != 0.0f) &&
+               if ((tb_scale.w != 0.0f) &&
                    (ct->dobreak == 0) &&
-                   (((xof - (tb->x / cu->fsize) + twidth) * cu->fsize) > tb->w + cu->xof * cu->fsize))
+                   (((xof - tb_scale.x) + twidth) > xof_scale + tb_scale.w))
                {
                        //              fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
                        for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
@@ -723,31 +799,33 @@ makebreak:
 
                        yof -= linedist;
 
-                       lineinfo[lnr].x_min     = (xof - xtrax) - (tb->x / cu->fsize);
-                       lineinfo[lnr].x_max     = tb->w / cu->fsize;
+                       lineinfo[lnr].x_min     = (xof - xtrax) - tb_scale.x;
+                       lineinfo[lnr].x_max     = tb_scale.w;
                        lineinfo[lnr].char_nr   = cnr;
                        lineinfo[lnr].wspace_nr = wsnr;
 
                        CLAMP_MIN(maxlen, lineinfo[lnr].x_min);
 
-                       if ((tb->h != 0.0f) &&
-                           ((-(yof - (tb->y / cu->fsize))) > ((tb->h / cu->fsize) - (linedist * cu->fsize)) - cu->yof) &&
-                           (cu->totbox > (curbox + 1)) )
+                       if ((tb_scale.h != 0.0f) &&
+                           (cu->totbox > (curbox + 1)) &&
+                           ((-(yof - tb_scale.y)) > (tb_scale.h - linedist) - yof_scale))
                        {
                                maxlen = 0;
-                               tb++;
                                curbox++;
-                               yof = cu->yof + tb->y / cu->fsize;
+
+                               textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / cu->fsize);
+
+                               yof = MARGIN_Y_MIN;
                        }
 
                        /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
 #if 0
                        if (ascii == '\n')
-                               xof = cu->xof;
+                               xof = xof_scale;
                        else
-                               xof = cu->xof + (tb->x / cu->fsize);
+                               xof = MARGIN_X_MIN;
 #else
-                       xof = cu->xof + (tb->x / cu->fsize);
+                       xof = MARGIN_X_MIN;
 #endif
                        lnr++;
                        cnr = 0;
@@ -761,9 +839,9 @@ makebreak:
                        ct->linenr = lnr;
                        ct->charnr = cnr++;
 
-                       tabfac = (xof - cu->xof + 0.01f);
+                       tabfac = (xof - MARGIN_X_MIN + 0.01f);
                        tabfac = 2.0f * ceilf(tabfac / 2.0f);
-                       xof = cu->xof + tabfac;
+                       xof = MARGIN_X_MIN + tabfac;
                }
                else {
                        EditFontSelBox *sb = NULL;
@@ -817,7 +895,7 @@ makebreak:
                        struct TempLineInfo *li;
 
                        for (i = 0, li = lineinfo; i < lnr; i++, li++) {
-                               li->x_min = (li->x_max - li->x_min) + cu->xof;
+                               li->x_min = (li->x_max - li->x_min) + xof_scale;
                        }
 
                        for (i = 0; i <= slen; i++) {
@@ -829,7 +907,7 @@ makebreak:
                        struct TempLineInfo *li;
 
                        for (i = 0, li = lineinfo; i < lnr; i++, li++) {
-                               li->x_min = ((li->x_max - li->x_min) + cu->xof) / 2.0f;
+                               li->x_min = ((li->x_max - li->x_min) + xof_scale) / 2.0f;
                        }
 
                        for (i = 0; i <= slen; i++) {
@@ -837,11 +915,11 @@ makebreak:
                                ct++;
                        }
                }
-               else if ((cu->spacemode == CU_FLUSH) && (cu->tb[0].w != 0.0f)) {
+               else if ((cu->spacemode == CU_FLUSH) && use_textbox) {
                        struct TempLineInfo *li;
 
                        for (i = 0, li = lineinfo; i < lnr; i++, li++) {
-                               li->x_min = ((li->x_max - li->x_min) + cu->xof);
+                               li->x_min = ((li->x_max - li->x_min) + xof_scale);
 
                                if (li->char_nr > 1) {
                                        li->x_min /= (float)(li->char_nr - 1);
@@ -858,7 +936,7 @@ makebreak:
                                ct++;
                        }
                }
-               else if ((cu->spacemode == CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) {
+               else if ((cu->spacemode == CU_JUSTIFY) && use_textbox) {
                        float curofs = 0.0f;
                        for (i = 0; i <= slen; i++) {
                                for (j = i;
@@ -875,7 +953,7 @@ makebreak:
                                                struct TempLineInfo *li;
 
                                                li = &lineinfo[ct->linenr];
-                                               curofs += ((li->x_max - li->x_min) + cu->xof) / (float)li->wspace_nr;
+                                               curofs += ((li->x_max - li->x_min) + xof_scale) / (float)li->wspace_nr;
                                        }
                                        ct->xof += curofs;
                                }
@@ -1143,6 +1221,9 @@ finally:
        }
 
        return ok;
+
+#undef MARGIN_X_MIN
+#undef MARGIN_Y_MIN
 }