[gimp] libgimpwidgets: add ratio expressions to eevl



commit 6caae9c53b22aed48ba8670afbc6a746863f96bb
Author: Ell <ell_se yahoo com>
Date:   Wed Oct 4 12:14:41 2017 -0400

    libgimpwidgets: add ratio expressions to eevl
    
    Ratio expressions have the form 'x : y' (the ':' operator has the
    highest precedence for a binary operator, and is left-associative).
    Given a reference value 'a', the expression evaluates to
    'a * (x / y)'.
    
    Ratio expressions can be controlled by the caller by:
    
      - Enabling or disabling them:  They're meant to be used when the
        eevl servers two paired entries, and can be disabled otherwise.
    
      - Setting the reference value:  That's normally the value of the
        "other" entry of the pair--the one not currently being
        evaluated.
    
      - Inverting the ratios:  Normally, one entry refers to the
        antecedent term of the ratio, and the other entry refers to the
        consequent term of the ratio.  When evaluating the latter one,
        the ratio should be inverted.

 libgimpwidgets/gimpeevl.c |   52 +++++++++++++++++++++++++++++++++++++-------
 libgimpwidgets/gimpeevl.h |   13 ++++++++++-
 2 files changed, 55 insertions(+), 10 deletions(-)
---
diff --git a/libgimpwidgets/gimpeevl.c b/libgimpwidgets/gimpeevl.c
index 2cb0a06..2bc4eaa 100644
--- a/libgimpwidgets/gimpeevl.c
+++ b/libgimpwidgets/gimpeevl.c
@@ -40,7 +40,9 @@
  *   expression    ::= term { ('+' | '-') term }*  |
  *                     <empty string> ;
  *
- *   term          ::= signed factor { ( '*' | '/' ) signed factor }* ;
+ *   term          ::= ratio { ( '*' | '/' ) ratio }* ;
+ *
+ *   ratio         ::= signed factor { ':' signed factor }* ;
  *
  *   signed factor ::= ( '+' | '-' )? factor ;
  *
@@ -123,6 +125,7 @@ static void             gimp_eevl_init                     (GimpEevl
 static GimpEevlQuantity gimp_eevl_complete                 (GimpEevl              *eva);
 static GimpEevlQuantity gimp_eevl_expression               (GimpEevl              *eva);
 static GimpEevlQuantity gimp_eevl_term                     (GimpEevl              *eva);
+static GimpEevlQuantity gimp_eevl_ratio                    (GimpEevl              *eva);
 static GimpEevlQuantity gimp_eevl_signed_factor            (GimpEevl              *eva);
 static GimpEevlQuantity gimp_eevl_factor                   (GimpEevl              *eva);
 static gboolean         gimp_eevl_accept                   (GimpEevl              *eva,
@@ -307,30 +310,61 @@ static GimpEevlQuantity
 gimp_eevl_term (GimpEevl *eva)
 {
   gboolean         division;
-  GimpEevlQuantity evaluated_signed_factors;
+  GimpEevlQuantity evaluated_ratios;
 
-  evaluated_signed_factors = gimp_eevl_signed_factor (eva);
+  evaluated_ratios = gimp_eevl_ratio (eva);
 
   for (division = FALSE;
        gimp_eevl_accept (eva, '*', NULL) ||
        (division = gimp_eevl_accept (eva, '/', NULL));
        division = FALSE)
     {
-      GimpEevlQuantity new_signed_factor = gimp_eevl_signed_factor (eva);
+      GimpEevlQuantity new_ratio = gimp_eevl_ratio (eva);
 
       if (division)
         {
-          evaluated_signed_factors.value     /= new_signed_factor.value;
-          evaluated_signed_factors.dimension -= new_signed_factor.dimension;
-
+          evaluated_ratios.value     /= new_ratio.value;
+          evaluated_ratios.dimension -= new_ratio.dimension;
         }
       else
         {
-          evaluated_signed_factors.value     *= new_signed_factor.value;
-          evaluated_signed_factors.dimension += new_signed_factor.dimension;
+          evaluated_ratios.value     *= new_ratio.value;
+          evaluated_ratios.dimension += new_ratio.dimension;
         }
     }
 
+  return evaluated_ratios;
+}
+
+static GimpEevlQuantity
+gimp_eevl_ratio (GimpEevl *eva)
+{
+  GimpEevlQuantity evaluated_signed_factors;
+
+  if (! eva->options.ratio_expressions)
+    return gimp_eevl_signed_factor (eva);
+
+  evaluated_signed_factors = gimp_eevl_signed_factor (eva);
+
+  while (gimp_eevl_accept (eva, ':', NULL))
+    {
+      GimpEevlQuantity new_signed_factor = gimp_eevl_signed_factor (eva);
+
+      if (eva->options.ratio_invert)
+        {
+          GimpEevlQuantity temp;
+
+          temp                     = evaluated_signed_factors;
+          evaluated_signed_factors = new_signed_factor;
+          new_signed_factor        = temp;
+        }
+
+      evaluated_signed_factors.value     *= eva->options.ratio_quantity.value /
+                                            new_signed_factor.value;
+      evaluated_signed_factors.dimension += eva->options.ratio_quantity.dimension -
+                                            new_signed_factor.dimension;
+    }
+
   return evaluated_signed_factors;
 }
 
diff --git a/libgimpwidgets/gimpeevl.h b/libgimpwidgets/gimpeevl.h
index 0546ace..c4c024a 100644
--- a/libgimpwidgets/gimpeevl.h
+++ b/libgimpwidgets/gimpeevl.h
@@ -59,18 +59,29 @@ typedef gboolean (* GimpEevlUnitResolverProc) (const gchar      *identifier,
  * GimpEevlOptions:
  * @unit_resolver_proc: Unit resolver callback.
  * @data:               Data passed to unit resolver.
+ * @ratio_expressions:  Allow ratio expressions
+ * @ratio_invert:       Invert ratios
+ * @ratio_quantity:     Quantity to multiply ratios by
  */
 typedef struct
 {
   GimpEevlUnitResolverProc unit_resolver_proc;
   gpointer                 data;
+
+  gboolean                 ratio_expressions;
+  gboolean                 ratio_invert;
+  GimpEevlQuantity         ratio_quantity;
 } GimpEevlOptions;
 
 #define GIMP_EEVL_OPTIONS_INIT                                                 \
   ((const GimpEevlOptions)                                                     \
   {                                                                            \
     .unit_resolver_proc = NULL,                                                \
-    .data               = NULL                                                 \
+    .data               = NULL,                                                \
+                                                                               \
+    .ratio_expressions  = FALSE,                                               \
+    .ratio_invert       = FALSE,                                               \
+    .ratio_quantity     = {0.0, 0}                                             \
   })
 
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]