]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Preliminary support for mixed percent and linear declarations
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 5 Jan 2010 18:38:11 +0000 (19:38 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 5 Jan 2010 18:38:11 +0000 (19:38 +0100)
gfxmenu/gui_box.c
gfxmenu/gui_canvas.c
gfxmenu/theme_loader.c
include/grub/gui.h

index 45028e5b181bacfed561bf7d15b9d9adcab4de32..38b15f96d263df062e8421319e9f854161322214 100644 (file)
@@ -93,7 +93,7 @@ layout_horizontally (grub_gui_box_t self, int modify_layout,
 
   struct component_node *cur;
   unsigned w = 0, mwfrac = 0, h = 0, x = 0;
-  grub_fixed_unsigned_t wfrac = 0;
+  grub_fixed_signed_t wfrac = 0;
   int bogus_frac = 0;
 
   for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
@@ -104,17 +104,14 @@ layout_horizontally (grub_gui_box_t self, int modify_layout,
       if (c->ops->get_minimal_size)
        c->ops->get_minimal_size (c, &mw, &mh);
 
-      if (!c->ishfrac && c->h > h)
+      if (c->h > (signed) h)
        h = c->h;
       if (mh > h)
        h = mh;
-      if (!c->iswfrac)
-       w += mw > c->w ? mw : c->w;
-      if (c->iswfrac)
-       {
-         wfrac += c->wfrac;
-         mwfrac += mw;
-       }
+      wfrac += c->wfrac;
+      w += c->w;
+      if (mw - c->w > 0)
+       mwfrac += mw - c->w;
     }
   if (wfrac > GRUB_FIXED_1 || (w > 0 && wfrac == GRUB_FIXED_1))
     bogus_frac = 1;
@@ -122,7 +119,7 @@ layout_horizontally (grub_gui_box_t self, int modify_layout,
   if (min_width)
     {
       if (wfrac < GRUB_FIXED_1)
-       *min_width = grub_fixed_ufu_divide (w, GRUB_FIXED_1 - wfrac);
+       *min_width = grub_fixed_sfs_divide (w, GRUB_FIXED_1 - wfrac);
       else
        *min_width = w;
       if (*min_width < w + mwfrac)
@@ -142,16 +139,14 @@ layout_horizontally (grub_gui_box_t self, int modify_layout,
 
       r.x = x;
       r.y = 0;
-      r.width = 32;
       r.height = h;
 
       if (c->ops->get_minimal_size)
        c->ops->get_minimal_size (c, &mw, &mh);
 
-      if (!c->iswfrac)
-       r.width = c->w;
-      if (c->iswfrac && !bogus_frac)
-       r.width = grub_fixed_ufu_multiply (self->bounds.width, c->wfrac);
+      r.width = c->w;
+      if (!bogus_frac)
+       r.width += grub_fixed_sfs_multiply (self->bounds.width, c->wfrac);
 
       if (r.width < mw)
        r.width = mw;
@@ -171,7 +166,7 @@ layout_vertically (grub_gui_box_t self, int modify_layout,
 
   struct component_node *cur;
   unsigned h = 0, mhfrac = 0, w = 0, y = 0;
-  grub_fixed_unsigned_t hfrac = 0;
+  grub_fixed_signed_t hfrac = 0;
   int bogus_frac = 0;
 
   for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
@@ -182,17 +177,14 @@ layout_vertically (grub_gui_box_t self, int modify_layout,
       if (c->ops->get_minimal_size)
        c->ops->get_minimal_size (c, &mw, &mh);
 
-      if (!c->iswfrac && c->w > w)
+      if (c->w > (signed) w)
        w = c->w;
       if (mw > w)
        w = mw;
-      if (!c->ishfrac)
-       h += mh > c->h ? mh : c->h;
-      if (c->ishfrac)
-       {
-         hfrac += c->hfrac;
-         mhfrac += mh;
-       }
+      hfrac += c->hfrac;
+      h += c->h;
+      if (mh - c->h > 0)
+       mhfrac += mh - c->h;
     }
   if (hfrac > GRUB_FIXED_1 || (h > 0 && hfrac == GRUB_FIXED_1))
     bogus_frac = 1;
@@ -200,7 +192,7 @@ layout_vertically (grub_gui_box_t self, int modify_layout,
   if (min_height)
     {
       if (hfrac < GRUB_FIXED_1)
-       *min_height = grub_fixed_ufu_divide (h, GRUB_FIXED_1 - hfrac);
+       *min_height = grub_fixed_sfs_divide (h, GRUB_FIXED_1 - hfrac);
       else
        *min_height = h;
       if (*min_height < h + mhfrac)
@@ -221,15 +213,13 @@ layout_vertically (grub_gui_box_t self, int modify_layout,
       r.x = 0;
       r.y = y;
       r.width = w;
-      r.height = 32;
 
       if (c->ops->get_minimal_size)
        c->ops->get_minimal_size (c, &mw, &mh);
 
-      if (!c->ishfrac)
-       r.height = c->h;
-      if (c->ishfrac)
-       r.height = grub_fixed_ufu_multiply (self->bounds.height, c->hfrac);
+      r.height = c->h;
+      if (!bogus_frac)
+       r.height += grub_fixed_sfs_multiply (self->bounds.height, c->hfrac);
 
       if (r.height < mh)
        r.height = mh;
index 8b55b2a731c5e996f25c60a8ac5340ab8c283086..b3919c2d3ea460e6803fbd28ef468cd81b36e693 100644 (file)
@@ -88,49 +88,51 @@ canvas_paint (void *vself, const grub_video_rect_t *region)
     {
       grub_video_rect_t r;
       grub_gui_component_t comp;
+      signed x, y, w, h;
 
       comp = cur->component;
 
-      r.x = 0;
-      r.y = 0;
-      r.width = 32;
-      r.height = 32;
-
-      if (!comp->iswfrac && comp->w)
-       r.width = comp->w;
-
-      if (!comp->ishfrac && comp->h)
-       r.height = comp->h;
-
-      if (!comp->isxfrac && comp->x)
-       r.x = comp->x;
-
-      if (!comp->isyfrac && comp->y)
-       r.y = comp->y;
-
-      if (comp->ishfrac && comp->hfrac)
-       r.height = grub_fixed_ufu_multiply (self->bounds.height, comp->hfrac);
-
-      if (comp->iswfrac && comp->wfrac)
-       r.width = grub_fixed_ufu_multiply (self->bounds.width, comp->wfrac);
-
-      if (comp->isxfrac && comp->xfrac)
-       r.x = grub_fixed_ufu_multiply (self->bounds.width, comp->xfrac);
-
-      if (comp->isyfrac && comp->yfrac)
-       r.y = grub_fixed_ufu_multiply (self->bounds.height, comp->yfrac);
+      w = grub_fixed_sfs_multiply (self->bounds.width, comp->wfrac) + comp->w;
+      h = grub_fixed_sfs_multiply (self->bounds.height, comp->hfrac) + comp->h;
+      x = grub_fixed_sfs_multiply (self->bounds.width, comp->xfrac) + comp->x;
+      y = grub_fixed_sfs_multiply (self->bounds.height, comp->yfrac) + comp->y;
 
       if (comp->ops->get_minimal_size)
        {
          unsigned mw;
          unsigned mh;
          comp->ops->get_minimal_size (comp, &mw, &mh);
-         if (r.width < mw)
-           r.width = mw;
-         if (r.height < mh)
-           r.height = mh;
+         if (w < (signed) mw)
+           w = mw;
+         if (h < (signed) mh)
+           h = mh;
        }
 
+      /* Sanity checks.  */
+      if (w <= 0)
+       w = 32;
+      if (h <= 0)
+       h = 32;
+
+      if (x >= (signed) self->bounds.width)
+       x = self->bounds.width - 32;
+      if (y >= (signed) self->bounds.height)
+       y = self->bounds.height - 32;
+
+      if (x < 0)
+       x = 0;
+      if (y < 0)
+       y = 0;
+
+      if (x + w >= (signed) self->bounds.width)
+       w = self->bounds.width - x;
+      if (y + h >= (signed) self->bounds.height)
+       h = self->bounds.height - y;
+
+      r.x = x;
+      r.y = y;
+      r.width = w;
+      r.height = h;
       comp->ops->set_bounds (comp, &r);
 
       /* Paint the child.  */
index 29bc1d2a62ab086258e6f6030d8e01969e257db4..09637d6b48b9e7692bd690780467ff40e17b63e0 100644 (file)
@@ -361,6 +361,40 @@ read_expression (struct parsebuf *p)
   return grub_new_substring (p->buf, start, end);
 }
 
+static grub_err_t
+parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop)
+{
+  signed num;
+  char *ptr;
+  int sig = 0;
+  *abs = 0;
+  *prop = 0;
+  ptr = value;
+  while (*ptr)
+    {
+      sig = 0;
+
+      while (*ptr == '-' || *ptr == '+')
+       {
+         if (*ptr == '-')
+           sig = !sig;
+         ptr++;
+       }
+
+      num = grub_strtoul (ptr, &ptr, 0);
+      if (grub_errno)
+       return grub_errno;
+      if (sig)
+       num = -num;
+      if (*ptr == '%')
+       *prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100);
+      else
+       *abs += num;
+    }
+  return GRUB_ERR_NONE;
+}
+
+
 /* Read a GUI object specification from the theme file.
    Any components created will be added to the GUI container PARENT.  */
 static grub_err_t
@@ -511,78 +545,16 @@ read_object (struct parsebuf *p, grub_gui_container_t parent)
 
       /* Handle the property value.  */
       if (grub_strcmp (property, "left") == 0)
-        {
-         unsigned num;
-         char *ptr;
-         num = grub_strtoul (value, &ptr, 0);
-         if (*ptr == '%')
-           {
-             component->isxfrac = 1;
-             component->xfrac
-               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
-           }
-         else
-           {
-             component->isxfrac = 0;
-             component->x = num;
-           }
-        }
+       parse_proportional_spec (value, &component->x, &component->xfrac);
       else if (grub_strcmp (property, "top") == 0)
-        {
-         unsigned num;
-         char *ptr;
-         num = grub_strtoul (value, &ptr, 0);
-         if (*ptr == '%')
-           {
-             component->isyfrac = 1;
-             component->yfrac
-               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
-           }
-         else
-           {
-             component->isyfrac = 0;
-             component->y = num;
-           }
-        }
+       parse_proportional_spec (value, &component->y, &component->yfrac);
       else if (grub_strcmp (property, "width") == 0)
-        {
-         unsigned num;
-         char *ptr;
-         num = grub_strtoul (value, &ptr, 0);
-         if (*ptr == '%')
-           {
-             component->iswfrac = 1;
-             component->wfrac
-               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
-           }
-         else
-           {
-             component->iswfrac = 0;
-             component->w = num;
-           }
-        }
+       parse_proportional_spec (value, &component->w, &component->wfrac);
       else if (grub_strcmp (property, "height") == 0)
-        {
-         unsigned num;
-         char *ptr;
-         num = grub_strtoul (value, &ptr, 0);
-         if (*ptr == '%')
-           {
-             component->ishfrac = 1;
-             component->hfrac
-               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
-           }
-         else
-           {
-             component->ishfrac = 0;
-             component->h = num;
-           }
-        }
+       parse_proportional_spec (value, &component->h, &component->hfrac);
       else
-        {
-          /* General property handling.  */
-          component->ops->set_property (component, property, value);
-        }
+       /* General property handling.  */
+       component->ops->set_property (component, property, value);
 
       grub_free (value);
       grub_free (property);
index 873d29e7665734794f35a8508659176bd4616687..7c47748386cd301fb73f6e7659a77a7372d38c52 100644 (file)
@@ -75,62 +75,50 @@ struct grub_gui_list_ops
                          grub_gfxmenu_model_t menu);
 };
 
-typedef grub_uint32_t grub_fixed_unsigned_t;
+typedef signed grub_fixed_signed_t;
 #define GRUB_FIXED_1 0x10000
 
-static inline unsigned
-grub_fixed_ufu_divide (grub_uint32_t a, grub_fixed_unsigned_t b)
+static inline signed
+grub_fixed_sfs_divide (signed a, grub_fixed_signed_t b)
 {
-  return (a << 16) / b;
+  return (a * GRUB_FIXED_1) / b;
 }
 
-static inline grub_fixed_unsigned_t
-grub_fixed_fuf_divide (grub_fixed_unsigned_t a, grub_uint32_t b)
+static inline grub_fixed_signed_t
+grub_fixed_fsf_divide (grub_fixed_signed_t a, signed b)
 {
   return a / b;
 }
 
-static inline unsigned
-grub_fixed_ufu_multiply (grub_uint32_t a, grub_fixed_unsigned_t b)
+static inline signed
+grub_fixed_sfs_multiply (signed a, grub_fixed_signed_t b)
 {
-  return (a * b) >> 16;
+  return (a * b) / GRUB_FIXED_1;
 }
 
-static inline unsigned
-grub_fixed_to_unsigned (grub_fixed_unsigned_t in)
+static inline signed
+grub_fixed_to_signed (grub_fixed_signed_t in)
 {
-  return in >> 16;
+  return in / GRUB_FIXED_1;
 }
 
-static inline grub_fixed_unsigned_t
-grub_unsigned_to_fixed (unsigned in)
+static inline grub_fixed_signed_t
+grub_signed_to_fixed (signed in)
 {
-  return in << 16;
+  return in * GRUB_FIXED_1;
 }
 
 struct grub_gui_component
 {
   struct grub_gui_component_ops *ops;
-  int isxfrac:1;
-  int isyfrac:1;
-  int iswfrac:1;
-  int ishfrac:1;
-  union {
-    unsigned x;
-    grub_fixed_unsigned_t xfrac;
-  };
-  union {
-    unsigned y;
-    grub_fixed_unsigned_t yfrac;
-  };
-  union {
-    unsigned w;
-    grub_fixed_unsigned_t wfrac;
-  };
-  union {
-    unsigned h;
-    grub_fixed_unsigned_t hfrac;
-  };
+  signed x;
+  grub_fixed_signed_t xfrac;
+  signed y;
+  grub_fixed_signed_t yfrac;
+  signed w;
+  grub_fixed_signed_t wfrac;
+  signed h;
+  grub_fixed_signed_t hfrac;
 };
 
 struct grub_gui_container