Evas textblock: Move native size calculation out of the regular layout.
authorTom Hacohen <tom@stosb.com>
Tue, 31 May 2011 12:55:51 +0000 (12:55 +0000)
committerTom Hacohen <tom@stosb.com>
Tue, 31 May 2011 12:55:51 +0000 (12:55 +0000)
SVN revision: 59843

legacy/evas/src/lib/canvas/evas_object_textblock.c

index b5ad1c8..b718117 100644 (file)
@@ -1771,11 +1771,14 @@ static void _text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti
  * @internal
  * Adjust the ascent/descent of the format and context.
  *
- * @param c The context to work on - Not NUL.
+ * @param maxascent The ascent to update - Not NUL.
+ * @param maxdescent The descent to update - Not NUL.
  * @param fmt The format to adjust - NOT NULL.
  */
 static void
-_layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
+_layout_format_ascent_descent_adjust(const Evas_Object *obj,
+      Evas_Coord *maxascent, Evas_Coord *maxdescent,
+      Evas_Object_Textblock_Format *fmt)
 {
    int ascent, descent;
 
@@ -1783,8 +1786,8 @@ _layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
      {
         //     ascent = c->ENFN->font_max_ascent_get(c->ENDT, fmt->font.font);
         //     descent = c->ENFN->font_max_descent_get(c->ENDT, fmt->font.font);
-        ascent = c->ENFN->font_ascent_get(c->ENDT, fmt->font.font);
-        descent = c->ENFN->font_descent_get(c->ENDT, fmt->font.font);
+        ascent = ENFN->font_ascent_get(ENDT, fmt->font.font);
+        descent = ENFN->font_descent_get(ENDT, fmt->font.font);
         if (fmt->linesize > 0)
           {
              if ((ascent + descent) < fmt->linesize)
@@ -1798,19 +1801,19 @@ _layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
              descent = descent * fmt->linerelsize;
              ascent = ascent * fmt->linerelsize;
           }
-        c->maxdescent += fmt->linegap;
-        c->maxdescent += ((ascent + descent) * fmt->linerelgap);
-        if (c->maxascent < ascent) c->maxascent = ascent;
-        if (c->maxdescent < descent) c->maxdescent = descent;
+        *maxdescent += fmt->linegap;
+        *maxdescent += ((ascent + descent) * fmt->linerelgap);
+        if (*maxascent < ascent) *maxascent = ascent;
+        if (*maxdescent < descent) *maxdescent = descent;
         if (fmt->linefill > 0.0)
           {
              int dh;
 
-             dh = c->obj->cur.geometry.h - (c->maxascent + c->maxdescent);
+             dh = obj->cur.geometry.h - (*maxascent + *maxdescent);
              if (dh < 0) dh = 0;
              dh = fmt->linefill * dh;
-             c->maxdescent += dh / 2;
-             c->maxascent += dh - (dh / 2);
+             *maxdescent += dh / 2;
+             *maxascent += dh - (dh / 2);
              // FIXME: set flag that says "if heigh changes - reformat"
           }
      }
@@ -1837,7 +1840,8 @@ _layout_line_new(Ctxt *c, Evas_Object_Textblock_Format *fmt)
    c->maxascent = c->maxdescent = 0;
    c->ln->line_no = -1;
    c->ln->par = c->par;
-   _layout_format_ascent_descent_adjust(c, fmt);
+   _layout_format_ascent_descent_adjust(c->obj, &c->maxascent,
+         &c->maxdescent, fmt);
 }
 
 /* par index functions */
@@ -2283,6 +2287,108 @@ _layout_line_order(Ctxt *c __UNUSED__, Evas_Object_Textblock_Line *line)
 #endif
 }
 
+/* FIXME: doc */
+static void
+_layout_calculate_format_item_size(const Evas_Object *obj,
+      const Evas_Object_Textblock_Format_Item *fi,
+      Evas_Coord *maxascent, Evas_Coord *maxdescent,
+      Evas_Coord *_y, Evas_Coord *_w, Evas_Coord *_h)
+{
+   /* Adjust sizes according to current line height/scale */
+   Evas_Coord w, h;
+   const char *p, *s;
+
+   s = fi->item;
+   w = fi->parent.w;
+   h = fi->parent.h;
+   switch (fi->size)
+     {
+      case SIZE:
+         if (!strncmp(s, "item", 4))
+           {
+              p = strstr(s, " size=");
+              if (p)
+                {
+                   p += 6;
+                   if (sscanf(p, "%ix%i", &w, &h) == 2)
+                     {
+                        w = w * obj->cur.scale;
+                        h = h * obj->cur.scale;
+                     }
+                }
+           }
+         break;
+      case SIZE_REL:
+         p = strstr((char *) s, " relsize=");
+         p += 9;
+         if (sscanf(p, "%ix%i", &w, &h) == 2)
+           {
+              int sz = 1;
+              if (fi->vsize == VSIZE_FULL)
+                {
+                   sz = *maxdescent + *maxascent;
+                }
+              else if (fi->vsize == VSIZE_ASCENT)
+                {
+                   sz = *maxascent;
+                }
+              w = (w * sz) / h;
+              h = sz;
+           }
+         break;
+      case SIZE_ABS:
+         /* Nothing to do */
+      default:
+         break;
+     }
+
+   switch (fi->size)
+     {
+      case SIZE:
+      case SIZE_ABS:
+         switch (fi->vsize)
+           {
+            case VSIZE_FULL:
+               if (fi->parent.h > (*maxdescent + *maxascent))
+                 {
+                    *maxascent += fi->parent.h - (*maxdescent + *maxascent);
+                    *_y = -*maxascent;
+                 }
+               else
+                  *_y = -(fi->parent.h - *maxdescent);
+               break;
+            case VSIZE_ASCENT:
+               if (fi->parent.h > *maxascent)
+                 {
+                    *maxascent = fi->parent.h;
+                    *_y = -fi->parent.h;
+                 }
+               else
+                  *_y = -fi->parent.h;
+               break;
+            default:
+               break;
+           }
+         break;
+      case SIZE_REL:
+         switch (fi->vsize)
+           {
+            case VSIZE_FULL:
+            case VSIZE_ASCENT:
+               *_y = -*maxascent;
+               break;
+            default:
+               break;
+           }
+         break;
+      default:
+         break;
+     }
+
+   *_w = w;
+   *_h = h;
+}
+
 /**
  * @internal
  * Order the items in the line, update it's properties and update it's
@@ -2312,7 +2418,8 @@ _layout_line_finalize(Ctxt *c, Evas_Object_Textblock_Format *fmt)
      }
 
    if (no_text)
-     _layout_format_ascent_descent_adjust(c, fmt);
+      _layout_format_ascent_descent_adjust(c->obj, &c->maxascent,
+            &c->maxdescent, fmt);
 
    EINA_INLIST_FOREACH(c->ln->items, it)
      {
@@ -2321,106 +2428,16 @@ _layout_line_finalize(Ctxt *c, Evas_Object_Textblock_Format *fmt)
              Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
              if (ti->parent.format->font.font)
                ti->baseline = c->ENFN->font_max_ascent_get(c->ENDT, ti->parent.format->font.font);
-             _layout_format_ascent_descent_adjust(c, ti->parent.format);
+             _layout_format_ascent_descent_adjust(c->obj, &c->maxascent,
+                   &c->maxdescent, ti->parent.format);
           }
         else
           {
              Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
              if (!fi->formatme) goto loop_advance;
-             /* Adjust sizes according to current line height/scale */
-               {
-                  Evas_Coord w, h;
-                  const char *p, *s;
-
-                  s = fi->item;
-                  w = fi->parent.w;
-                  h = fi->parent.h;
-                  switch (fi->size)
-                    {
-                     case SIZE:
-                        if (!strncmp(s, "item", 4))
-                          {
-                             p = strstr(s, " size=");
-                             if (p)
-                               {
-                                  p += 6;
-                                  if (sscanf(p, "%ix%i", &w, &h) == 2)
-                                    {
-                                       w = w * c->obj->cur.scale;
-                                       h = h * c->obj->cur.scale;
-                                    }
-                               }
-                          }
-                        break;
-                     case SIZE_REL:
-                        p = strstr((char *) s, " relsize=");
-                        p += 9;
-                        if (sscanf(p, "%ix%i", &w, &h) == 2)
-                          {
-                             int sz = 1;
-                             if (fi->vsize == VSIZE_FULL)
-                               {
-                                  sz = c->maxdescent + c->maxascent;
-                               }
-                             else if (fi->vsize == VSIZE_ASCENT)
-                               {
-                                  sz = c->maxascent;
-                               }
-                             w = (w * sz) / h;
-                             h = sz;
-                          }
-                        break;
-                     case SIZE_ABS:
-                        /* Nothing to do */
-                     default:
-                        break;
-                    }
-                  fi->parent.w = fi->parent.adv = w;
-                  fi->parent.h = h;
-               }
-
-             switch (fi->size)
-               {
-                case SIZE:
-                case SIZE_ABS:
-                   switch (fi->vsize)
-                     {
-                      case VSIZE_FULL:
-                         if (fi->parent.h > (c->maxdescent + c->maxascent))
-                           {
-                              c->maxascent += fi->parent.h - (c->maxdescent + c->maxascent);
-                              fi->y = -c->maxascent;
-                           }
-                         else
-                           fi->y = -(fi->parent.h - c->maxdescent);
-                         break;
-                      case VSIZE_ASCENT:
-                         if (fi->parent.h > c->maxascent)
-                           {
-                              c->maxascent = fi->parent.h;
-                              fi->y = -fi->parent.h;
-                           }
-                         else
-                           fi->y = -fi->parent.h;
-                         break;
-                      default:
-                         break;
-                     }
-                   break;
-                case SIZE_REL:
-                   switch (fi->vsize)
-                     {
-                      case VSIZE_FULL:
-                      case VSIZE_ASCENT:
-                         fi->y = -c->maxascent;
-                         break;
-                      default:
-                         break;
-                     }
-                   break;
-                default:
-                   break;
-               }
+             _layout_calculate_format_item_size(c->obj, fi, &c->maxascent,
+                   &c->maxdescent, &fi->y, &fi->parent.w, &fi->parent.h);
+             fi->parent.adv = fi->parent.w;
           }
 
 loop_advance:
@@ -8099,16 +8116,92 @@ evas_object_textblock_size_formatted_get(const Evas_Object *obj, Evas_Coord *w,
    if (h) *h = o->formatted.h;
 }
 
+/* FIXME: doc */
+static void
+_size_native_calc_paragraph_size(const Evas_Object *obj,
+      const Evas_Object_Textblock *o,
+      const Evas_Object_Textblock_Paragraph *par,
+      Evas_Coord *_w, Evas_Coord *_h)
+{
+   Eina_List *i;
+   Evas_Object_Textblock_Item *it;
+   Evas_Coord x = 0, y = 0, wmax = 0, h = 0, ascent = 0, descent = 0;
+
+   EINA_LIST_FOREACH(par->logical_items, i, it)
+     {
+        if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
+          {
+             Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
+             if (fi->item && (_IS_LINE_SEPARATOR(fi->item) ||
+                      _IS_PARAGRAPH_SEPARATOR(o, fi->item)))
+               {
+                  /* If there are no text items yet, calc ascent/descent
+                   * according to the current format. */
+                  if (ascent + descent == 0)
+                     _layout_format_ascent_descent_adjust(obj, &ascent,
+                           &descent, it->format);
+
+                  if (ascent + descent > h)
+                     h = ascent + descent;
+                  if (x + it->adv > wmax)
+                     wmax = x + it->adv;
+                  y += h;
+                  x = h = 0;
+                  ascent = descent = 0;
+               }
+             else
+               {
+                  Evas_Coord fw, fh, fy;
+
+                  _layout_calculate_format_item_size(obj, fi, &ascent,
+                        &descent, &fy, &fw, &fh);
+
+                  if (fh > h)
+                     h = fh;
+                  x += fw;
+               }
+          }
+        else
+          {
+             _layout_format_ascent_descent_adjust(obj, &ascent,
+                   &descent, it->format);
+             x += it->adv;
+          }
+     }
+
+   /* Do the last addition */
+   if (ascent + descent > h)
+      h = ascent + descent;
+   if (x > wmax)
+      wmax = x;
+
+   *_h = y + h;
+   *_w = wmax;
+}
+
 EAPI void
 evas_object_textblock_size_native_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
 {
    TB_HEAD();
    if (!o->native.valid)
      {
-       _layout(obj,
-               1,
-               -1, -1,
-               &o->native.w, &o->native.h);
+        Evas_Coord wmax = 0, hmax = 0;
+        Evas_Object_Textblock_Paragraph *par;
+        /* We just want the layout objects to update, should probably
+         * split that. */
+        if (!o->formatted.valid) _relayout(obj);
+        EINA_INLIST_FOREACH(o->paragraphs, par)
+          {
+             Evas_Coord tw, th;
+             _size_native_calc_paragraph_size(obj, o, par, &tw, &th);
+             if (tw > wmax)
+                wmax = tw;
+             hmax += th;
+          }
+
+        o->native.w = wmax;
+        o->native.h = hmax;
+
        o->native.valid = 1;
         o->content_changed = 0;
         o->format_changed = EINA_FALSE;